摘要:阿里提出里面提供機(jī)制,即在退出前先等會兒,這樣可以減少退出次數(shù)。優(yōu)點(diǎn)性能較阿里好缺點(diǎn)只適用于獨(dú)占物理核場景狀態(tài)社區(qū)討論中,比較大可能被接受。針對不同的業(yè)務(wù)模型,采用不同的機(jī)制最大化業(yè)務(wù)性能。
本文由作者朱益軍授權(quán)網(wǎng)易云社區(qū)發(fā)布。
簡介
在實(shí)際業(yè)務(wù)中,guest執(zhí)行HLT指令是導(dǎo)致虛擬化overhead的一個(gè)重要原因。如[1].
KVM halt polling特性就是為了解決這一個(gè)問題被引入的,它在Linux 4.3-rc1被合入主干內(nèi)核,其基本原理是當(dāng)guest idle發(fā)生vm-exit時(shí),host 繼續(xù)polling一段時(shí)間,用于減少guest的業(yè)務(wù)時(shí)延。進(jìn)一步講,在vcpu進(jìn)入idle之后,guest內(nèi)核默認(rèn)處理是執(zhí)行HLT指令,就會發(fā)生vm-exit,host kernel并不馬上讓出物理核給調(diào)度器,而是poll一段時(shí)間,若guest在這段時(shí)間內(nèi)被喚醒,便可以馬上調(diào)度回該vcpu線程繼續(xù)運(yùn)行。
polling機(jī)制帶來時(shí)延上的降低,至少是一個(gè)線程調(diào)度周期,通常是幾微妙,但最終的性能提升是跟guest內(nèi)業(yè)務(wù)模型相關(guān)的。如果在host kernel polling期間,沒有喚醒事件發(fā)生或是運(yùn)行隊(duì)列里面其他任務(wù)變成runnable狀態(tài),那么調(diào)度器就會被喚醒去干其他任務(wù)的事。因此,halt polling機(jī)制對于那些在很短時(shí)間間隔就會被喚醒一次的業(yè)務(wù)特別有效。
代碼流程
guest執(zhí)行HLT指令發(fā)生vm-exit后,kvm處理該異常,在kvm_emulate_halt處理最后調(diào)用kvm_vcpu_halt(vcpu)。
int kvm_vcpu_halt(struct kvm_vcpu *vcpu){
++vcpu->stat.halt_exits; if (lapic_in_kernel(vcpu)) { vcpu->arch.mp_state = KVM_MP_STATE_HALTED; return 1; } else { vcpu->run->exit_reason = KVM_EXIT_HLT; return 0; }
}
將mp_state的值置為KVM_MP_STATE_HALTED,并返回1。
static int vcpu_run(struct kvm_vcpu vcpu){ int r; struct kvm kvm = vcpu->kvm;
vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); for (;;) { if (kvm_vcpu_running(vcpu)) { r = vcpu_enter_guest(vcpu); } else { r = vcpu_block(kvm, vcpu); } if (r <= 0) break; //省略 }
}
由于kvm處理完halt異常后返回1,故主循環(huán)不退出,但在下一個(gè)循環(huán)時(shí)kvm_vcpu_running(vcpu)返回false,所以進(jìn)入vcpu_block()分支,隨機(jī)調(diào)用kvm_vcpu_block()。
通用的halt polling代碼在virt/kvm/kvm_main.c文件中的額kvm_vcpu_block()函數(shù)中實(shí)現(xiàn)。
ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);do { /*
* This sets KVM_REQ_UNHALT if an interrupt * arrives. */ if (kvm_vcpu_check_block(vcpu) < 0) { ++vcpu->stat.halt_successful_poll; if (!vcpu_valid_wakeup(vcpu)) ++vcpu->stat.halt_poll_invalid; goto out; } cur = ktime_get();
} while (single_task_running() && ktime_before(cur, stop));
情況一:如果當(dāng)前物理核上沒有其他task處于running狀態(tài),而且在polling時(shí)間間隔內(nèi),那么就一直等著,直到kvm_vcpu_check_block(vcpu) < 0,即vcpu等待的中斷到達(dá),便跳出循環(huán)。
out:
block_ns = ktime_to_ns(cur) - ktime_to_ns(start); if (!vcpu_valid_wakeup(vcpu)) shrink_halt_poll_ns(vcpu); else if (halt_poll_ns) { if (block_ns <= vcpu->halt_poll_ns) ; /* we had a long block, shrink polling */ else if (vcpu->halt_poll_ns && block_ns > halt_poll_ns) shrink_halt_poll_ns(vcpu); /* we had a short halt and our poll time is too small */ else if (vcpu->halt_poll_ns < halt_poll_ns && block_ns < halt_poll_ns) grow_halt_poll_ns(vcpu); } else vcpu->halt_poll_ns = 0; trace_kvm_vcpu_wakeup(block_ns, waited, vcpu_valid_wakeup(vcpu)); kvm_arch_vcpu_block_finish(vcpu);
這段代碼主要用于調(diào)整下一次polling的等待時(shí)間。若block_ns大于halt_poll_ns,即vcpu halt時(shí)間很短就被喚醒了,則把下一次的halt_poll_ns調(diào)長;否則,減短。
情況二:如果當(dāng)前物理核上其他task變成running態(tài),或polling時(shí)間到期,則喚醒調(diào)度器,調(diào)度其他任務(wù),如下代碼。
for (;;) {
prepare_to_swait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE); if (kvm_vcpu_check_block(vcpu) < 0) break; waited = true; schedule(); }
模塊參數(shù)說明
Module Parameter Description default Value
halt_poll_ns The global max polling interval which defines the ceiling value which defines the ceiling value which defines the ceiling value of the polling interval for each vcpu. KVM_HALT_POLL_NS_DEFAULT (per arch value)
halt_poll_ns_grow The value by which the halt polling interval is multiplied polling interval is multiplied polling interval is multiplied in the grow_halt_poll_ns() function. 2
halt_poll_ns_shrink The value by which the halt polling interval is divided in the shrink_halt_poll_ns() function. 0
kvm用這3個(gè)參數(shù)來動態(tài)調(diào)整最大halt polling時(shí)長。debugfs下/sys/module/kvm/parameters/存放著這3個(gè)模塊參數(shù)的默認(rèn)值。X86架構(gòu)下,KVM_HALT_POLL_NS_DEFAULT默認(rèn)值為400000。 grow一次,值乘以halt_poll_ns_grow:
static void grow_halt_poll_ns(struct kvm_vcpu *vcpu){
unsigned int old, val, grow; old = val = vcpu->halt_poll_ns; grow = READ_ONCE(halt_poll_ns_grow); /* 10us base */ if (val == 0 && grow) val = 10000; else val *= grow; if (val > halt_poll_ns) val = halt_poll_ns; vcpu->halt_poll_ns = val; trace_kvm_halt_poll_ns_grow(vcpu->vcpu_id, val, old);
}
shrink一次,值除以halt_poll_ns_shrink,當(dāng)前系統(tǒng)該參數(shù)為0,說明在設(shè)定的polling時(shí)長下虛擬機(jī)未被喚醒,那么下一次polling時(shí)長降到基準(zhǔn)值10us:
static void shrink_halt_poll_ns(struct kvm_vcpu *vcpu){
unsigned int old, val, shrink; old = val = vcpu->halt_poll_ns; shrink = READ_ONCE(halt_poll_ns_shrink); if (shrink == 0) val = 0; else val /= shrink; vcpu->halt_poll_ns = val; trace_kvm_halt_poll_ns_shrink(vcpu->vcpu_id, val, old);
}
值得注意幾點(diǎn)
該機(jī)制有可能導(dǎo)致物理CPU實(shí)際空閑的情況下占用率表現(xiàn)為100%。因?yàn)槿绻鹓uest上業(yè)務(wù)模型是隔一段時(shí)間被喚醒一次來處理很少量的流量,并且這個(gè)時(shí)間間隔比kvm halt_poll_ns短,那么host將poll整個(gè)虛擬機(jī)的block時(shí)間,cpu占用率也會沖上100%。
halt polling是電源能耗和業(yè)務(wù)時(shí)延的一個(gè)權(quán)衡。為了減少進(jìn)入guest的時(shí)延,idle cpu時(shí)間轉(zhuǎn)換為host kernel時(shí)間。
該機(jī)制只有在CPU上沒有其他running任務(wù)的情況得以應(yīng)用,不然polling動作被立馬終止,喚醒調(diào)度器,調(diào)度其他進(jìn)程。
延伸閱讀
業(yè)界針對虛擬機(jī)idle這個(gè)課題有比較多的研究,因?yàn)樗鼛砹吮容^大的overhead。主要可以歸結(jié)為以下幾種:
idle=poll,即把虛擬機(jī)idle時(shí)一直polling,空轉(zhuǎn),不退出。這樣不利于物理CPU超線程的發(fā)揮。
阿里提出guest里面提供halt polling機(jī)制,即在VM退出前先等會兒,這樣可以減少VM退出次數(shù)。 --- 優(yōu)點(diǎn):性能較社區(qū)halt polling機(jī)制好;缺點(diǎn):需要修改guest內(nèi)核;狀態(tài):社區(qū)尚未接收 https://lwn.net/Articles/732236/
AWS及騰訊考慮guest HLT指令不退出。 --- 優(yōu)點(diǎn):性能較阿里好;缺點(diǎn):只適用于vcpu獨(dú)占物理核場景;狀態(tài):社區(qū)討論中,比較大可能被接受。https://patchwork.kernel.org/...
idle等于mwait及mwait不退出。 --- 需要高版本kvm及高版本guest內(nèi)核支持。
總結(jié)
如何高效地處理虛擬機(jī)idle是提升虛擬化性能的研究點(diǎn)。針對不同的業(yè)務(wù)模型,采用不同的機(jī)制最大化業(yè)務(wù)性能。后續(xù)將在考拉及其他業(yè)務(wù)上逐個(gè)驗(yàn)證這些方案。
參考文檔
https://www.linux-kvm.org/ima...
http://events17.linuxfoundati...
http://events17.linuxfoundati...
https://www.kernel.org/doc/Do...
免費(fèi)領(lǐng)取驗(yàn)證碼、內(nèi)容安全、短信發(fā)送、直播點(diǎn)播體驗(yàn)包及云服務(wù)器等套餐
更多網(wǎng)易技術(shù)、產(chǎn)品、運(yùn)營經(jīng)驗(yàn)分享請?jiān)L問網(wǎng)易云社區(qū)。
文章來源: 網(wǎng)易云社區(qū)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/25360.html
摘要:和的云計(jì)算功能特點(diǎn)對比正式這個(gè)戰(zhàn)爭或者說趨勢的一個(gè)生動寫照。總而言之,目前調(diào)度器將只會對部署虛擬機(jī)環(huán)節(jié)有影響。目前有一個(gè)孵化項(xiàng)目其作用是為提供虛擬機(jī)級別高可用支持。容錯(cuò)在中沒有針對于容錯(cuò)的功能,并且截至目前也沒有計(jì)劃去完成這些功能。 OpenStack中國社區(qū)編者按:在云計(jì)算生態(tài)系統(tǒng)中,有兩種類型的用戶需要使用云計(jì)算資源:傳統(tǒng)型(Traditional IT applications)和在互...
摘要:近期非常火熱,無論是從上的代碼活躍度,還是宣布在中正式支持,都給業(yè)界一個(gè)信號,這是一項(xiàng)創(chuàng)新型的技術(shù)解決方案。可以簡化部署多種應(yīng)用實(shí)例工作,比如應(yīng)用后臺應(yīng)用數(shù)據(jù)庫應(yīng)用大數(shù)據(jù)應(yīng)用比如集群消息隊(duì)列等等都可以打包成一個(gè)部署。 1. docker是什么 Docker is an open-source engine that automates the deployment of any...
摘要:分析惡意軟件有很多方法。這是一個(gè)虛擬化環(huán)境下的惡意軟件分析系統(tǒng)。整體上,基于虛擬機(jī)技術(shù),使用中央控制系統(tǒng)和模塊設(shè)計(jì),結(jié)合的自動化特征,已經(jīng)是頗為自動化的惡意軟件行為研究環(huán)境。加密的通訊幾乎不可能直接分析。 分析惡意軟件(malicious ware)有很多方法。請容我不自量力推薦兩個(gè)開放源代碼的免費(fèi)系統(tǒng) Cuckoo 和 MalWasm 。這是一個(gè)虛擬化環(huán)境下的惡意軟件分析系統(tǒng)。 基...
閱讀 3686·2021-09-22 15:34
閱讀 1197·2019-08-29 17:25
閱讀 3407·2019-08-29 11:18
閱讀 1381·2019-08-26 17:15
閱讀 1751·2019-08-23 17:19
閱讀 1239·2019-08-23 16:15
閱讀 726·2019-08-23 16:02
閱讀 1345·2019-08-23 15:19