资讯专栏INFORMATION COLUMN

KVM halt-polling机制分析

wfc_666 / 2560人阅读

摘要:阿里提出里面提供机制,即在退出前先等会儿,这样可以减少退出次数。优点性能较阿里好缺点只适用于独占物理核场景状态社区讨论中,比较大可能被接受。针对不同的业务模型,采用不同的机制最大化业务性能。

本文由作者朱益军授权网易云社区发布。

简介
在实际业务中,guest执行HLT指令是导致虚拟化overhead的一个重要原因。如[1].

KVM halt polling特性就是为了解决这一个问题被引入的,它在Linux 4.3-rc1被合入主干内核,其基本原理是当guest idle发生vm-exit时,host 继续polling一段时间,用于减少guest的业务时延。进一步讲,在vcpu进入idle之后,guest内核默认处理是执行HLT指令,就会发生vm-exit,host kernel并不马上让出物理核给调度器,而是poll一段时间,若guest在这段时间内被唤醒,便可以马上调度回该vcpu线程继续运行。

polling机制带来时延上的降低,至少是一个线程调度周期,通常是几微妙,但最终的性能提升是跟guest内业务模型相关的。如果在host kernel polling期间,没有唤醒事件发生或是运行队列里面其他任务变成runnable状态,那么调度器就会被唤醒去干其他任务的事。因此,halt polling机制对于那些在很短时间间隔就会被唤醒一次的业务特别有效。

代码流程
guest执行HLT指令发生vm-exit后,kvm处理该异常,在kvm_emulate_halt处理最后调用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,故主循环不退出,但在下一个循环时kvm_vcpu_running(vcpu)返回false,所以进入vcpu_block()分支,随机调用kvm_vcpu_block()。

通用的halt polling代码在virt/kvm/kvm_main.c文件中的额kvm_vcpu_block()函数中实现。

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));
情况一:如果当前物理核上没有其他task处于running状态,而且在polling时间间隔内,那么就一直等着,直到kvm_vcpu_check_block(vcpu) < 0,即vcpu等待的中断到达,便跳出循环。

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);

这段代码主要用于调整下一次polling的等待时间。若block_ns大于halt_poll_ns,即vcpu halt时间很短就被唤醒了,则把下一次的halt_poll_ns调长;否则,减短。

情况二:如果当前物理核上其他task变成running态,或polling时间到期,则唤醒调度器,调度其他任务,如下代码。

for (;;) {

    prepare_to_swait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);        if (kvm_vcpu_check_block(vcpu) < 0)            break;

    waited = true;
    schedule();
}

模块参数说明
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个参数来动态调整最大halt polling时长。debugfs下/sys/module/kvm/parameters/存放着这3个模块参数的默认值。X86架构下,KVM_HALT_POLL_NS_DEFAULT默认值为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,当前系统该参数为0,说明在设定的polling时长下虚拟机未被唤醒,那么下一次polling时长降到基准值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);

}
值得注意几点
该机制有可能导致物理CPU实际空闲的情况下占用率表现为100%。因为如果guest上业务模型是隔一段时间被唤醒一次来处理很少量的流量,并且这个时间间隔比kvm halt_poll_ns短,那么host将poll整个虚拟机的block时间,cpu占用率也会冲上100%。

halt polling是电源能耗和业务时延的一个权衡。为了减少进入guest的时延,idle cpu时间转换为host kernel时间。

该机制只有在CPU上没有其他running任务的情况得以应用,不然polling动作被立马终止,唤醒调度器,调度其他进程。

延伸阅读
业界针对虚拟机idle这个课题有比较多的研究,因为它带来了比较大的overhead。主要可以归结为以下几种:

idle=poll,即把虚拟机idle时一直polling,空转,不退出。这样不利于物理CPU超线程的发挥。

阿里提出guest里面提供halt polling机制,即在VM退出前先等会儿,这样可以减少VM退出次数。 --- 优点:性能较社区halt polling机制好;缺点:需要修改guest内核;状态:社区尚未接收 https://lwn.net/Articles/732236/

AWS及腾讯考虑guest HLT指令不退出。 --- 优点:性能较阿里好;缺点:只适用于vcpu独占物理核场景;状态:社区讨论中,比较大可能被接受。https://patchwork.kernel.org/...

idle等于mwait及mwait不退出。 --- 需要高版本kvm及高版本guest内核支持。

总结
如何高效地处理虚拟机idle是提升虚拟化性能的研究点。针对不同的业务模型,采用不同的机制最大化业务性能。后续将在考拉及其他业务上逐个验证这些方案。

参考文档
https://www.linux-kvm.org/ima...

http://events17.linuxfoundati...

http://events17.linuxfoundati...

https://www.kernel.org/doc/Do...

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请访问网易云社区。

文章来源: 网易云社区

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25360.html

相关文章

  • 云计算战争:OpenStack vs VMware—定位分析、功能对比、发展趋势

    摘要:和的云计算功能特点对比正式这个战争或者说趋势的一个生动写照。总而言之,目前调度器将只会对部署虚拟机环节有影响。目前有一个孵化项目其作用是为提供虚拟机级别高可用支持。容错在中没有针对于容错的功能,并且截至目前也没有计划去完成这些功能。 OpenStack中国社区编者按:在云计算生态系统中,有两种类型的用户需要使用云计算资源:传统型(Traditional IT applications)和在互...

    shiyang6017 评论0 收藏0
  • Docker简介

    摘要:近期非常火热,无论是从上的代码活跃度,还是宣布在中正式支持,都给业界一个信号,这是一项创新型的技术解决方案。可以简化部署多种应用实例工作,比如应用后台应用数据库应用大数据应用比如集群消息队列等等都可以打包成一个部署。 1. docker是什么 Docker is an open-source engine that automates the deployment of any...

    李义 评论0 收藏0
  • 恶意软件分析工具 Cuckoo 和 Malwasm

    摘要:分析恶意软件有很多方法。这是一个虚拟化环境下的恶意软件分析系统。整体上,基于虚拟机技术,使用中央控制系统和模块设计,结合的自动化特征,已经是颇为自动化的恶意软件行为研究环境。加密的通讯几乎不可能直接分析。 分析恶意软件(malicious ware)有很多方法。请容我不自量力推荐两个开放源代码的免费系统 Cuckoo 和 MalWasm 。这是一个虚拟化环境下的恶意软件分析系统。 基...

    Ilikewhite 评论0 收藏0

发表评论

0条评论

wfc_666

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<