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,卻多了時間的佔用。

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