main_loop_wait vs aio_poll

因为一次性能调优过程看到这块代码,大致过了一下,发现主线程和iothread的内部实现还有点区别。

main_loop_wait是qemu进程中的主线程事件循环,其大致工作流程为:
1. 触发main_loop_poll_notifiers(可能会修改timeout和添加fd到gpollfds)
2. 得到当前事件源的时钟系统中最近的timeout
3.调用g_main_context_prepare获取ready的事件源的max_priority
4.调用g_main_context_query获取满足max_priority的所有事件到gpollfds,并更新timeout
5.poll
6.g_main_context_check检查max_priority级别的所有事件是否有ready的
7.g_main_context_dispatch分发事件
8.再次触发触发main_loop_poll_notifiers,但是状态更新为MAIN_LOOP_POLL_OK。
9.处理到期时钟

这个流程处于一个大循环中,并且保证高级别的事件源中的事件优先处理。main_loop_poll_notifiers中生成的事件比较特殊,不受优先级限制。3,6,7中的函数隐式的调用了下面的回调函数。

static GSourceFuncs aio_source_funcs = {
    aio_ctx_prepare,
    aio_ctx_check,
    aio_ctx_dispatch,
    aio_ctx_finalize
};

aio_ctx_prepare计算bottom half与时钟系统两者的timeout并取最小,如果有ready的则返回true。其中bottom half中idle bh的超时是10ms,其它bh是立即处理。
aio_ctx_check检查bh,事件,时钟系统是否有ready并返回bool
aio_ctx_dispatch调用aio_dispatch,处理所有被调度的bh,所有ready事件,所有超时timer
aio_ctx_finalize不用多说。

iothread用aio_poll,aio_poll里额外增加了一个polling机制,先轮询一定的时间片然后再poll(),时间片大小由ctx->poll_ns与计算的timeout取最小值,timeout由bh与最近的timer决定。而且没有对g_main_context_xxx做调用而是完全定制化,poll()退出后立即更新ctx->poll_ns。依据就是这次消耗的时间在下次poll也会等待相同的时间。然后就是aio_bh_poll(),aio_dispatch_ready_handlers(),timerlistgroup_run_timers()的调用,这三者在主线程aio_ctx_dispatch()也有类似的调用。而且是否轮询一定时间片受监听的事件是否支持io_poll影响,只要有一个事件不支持io_poll,那就不会轮询而是直接poll(),这种轮询机制印象中cpu thread也有,而且guest内核中也有一套叫haltpoll。

问题:这种轮询依赖于推测的准确性,会抢占部分cpu,iothread与其他线程默认共用一套cpu affinity,对性能应用场景有多大影响?特别是那些cpu thread,如果guest内部中断绑核,那对应的iothread是与vcpu占用同一pcpu好还是分开好?占用同一pcpu,调度省掉了reschedule ipi,却多了时间的占用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章