kvm latency tunning
注:参考tencent-cloud的wangpengli的报告
报告的目标是优化kvm hypervisor的latency性能,主要有以下几点。
TLB Shootdown
TLB:Translation Lookaside Buffer,转译后备缓冲区(页表缓存),存放虚拟地址映射物理地址。
TLB shootdown一般通过IPI方式实现。
问题
TBL shootdown preemption问题。
在裸金属架构(bare-metal)上,远程TLB刷新导致发起IPI的CPU上的进程busy wait还是可以接受的。
但是在客户机中,vCPU此时可能已经被抢占或阻塞了,那么发起IPI的vCPU可能就会busy wait很长一段时间,而且会浪费CPU资源来唤醒shootdown目标vCPU。
通常,remote target vCPU在获得抢占到得到重新调度之间的latency远远大于TLB shootdown操作本身的latency。
解决
Paravirtualized TLB shootdown,半虚拟化TLB shootdown。
该方案中,不再需要等待睡眠中的vCPU,而是由KVM在vCPU再次开始运行时去刷新TLB。该方案可以避免那些已被抢占的vCPU去steal正在运行的vCPU的CPU时间。
实现
KVM_VCPU_PREEMPTED flag
- 当vCPU被抢占或被调度出去时,在host与guest共享的memory上打上该flag;
- 下一次vm entry时,抹掉该flag;
pv_mmu_ops.flush_tlb_others
- 发送IPIs给active vCPUs,并且通过KVM_VCPU_FLUSH_TLB标记来标识那些被抢占的vCPU;
- 当vCPU下次被调度时,如果有KVM_VCPU_FLUSH_TLB标记,则KVM通过INVVPID来flush TLB;
Exitless IPIs
问题
x2APIC模式下,Linux内核:
- cluster mode:按cluster来发送IPI(每个cluster最多16个逻辑CPU);
- physical mode:一个一个CPU的发送IPI;
每次写ICR寄存器(中断控制寄存器)都会引起vm exit,当有很多VMs虚机时,较多的IPIs以function call interrupts严重影响性能。
解决
- 在guest客户机中使用bitmap来标记vCPU
- 通过hypercall机制来发送IPIs至multiple vCPUs,64位系统下,该hypercall接口最多一次发送128个vCPUs目标,32位系统一次最多发送64个vCPUs目标;
- 通过bitmap来发送IPIs至目标vCPUs。
mwait/hlt/pause
允许用户态程序去关闭MWAIT/HLT/PAUSE vm exits,这样guest可以将物理CPU进入power saving状态(常规是将物理CPU至于idle=poll状态),而其他CPU就可以进入turbo boost超频状态从而提升性能。
Virtual IPI Fastpath
通过KVM来IPI Fastpath透传,在KVM VM Exit的状态早期就把IPI发送到目标vCPU。
- 在host主机interrupts发生之前;
- 在一些昂贵的操作消耗之前,比如KVM’s SRCU lock获取之前就发送IPI Fastpath至目标vCPU。
Virtual TSC-Deadline timer Fastpath
问题
- arm timer 以及 timer fire都会引起VM Exit;
- 在emulation作用之前,需要各种housekeeping task运行;
解决
由于TSC Deadline timer产生的VM Exit:
- 在vCPU的loop中就缩减各种housekeeping task的运行;
- 处理完之后立即VM Entry;
Boost Preempted vCPU
问题
多数情况下,smp_call_function_many调用是同步产生的(用于发送IPI,会产生VM Exit),优化的角度不能只局限于锁持有者(我的理解,比如这里的Busy waiting的vCPU0),IPI发送的目标vCPUs也是性能优化点,比如下图中的Tsched_delay大小就是由vCPU2决定的。
解决
LWP问题:由于自旋锁的先到先得的算法,当hypervisor抢占还未获得lock的next waiter等待者,即使lock被释放了,也不允许其他任务去获得lock只能等到刚才那个next waiter运行之后才可以。
那怎么办?拥有lock的vCPU在释放锁时,将锁让给queue头部vCPU,加快queue head vCPU的运行到来。
Yield to IPI Target
当发送IPI至多个vCPUs时:
- 如果出现vCPU被抢占,则让给该vCPU;
- 让给找到的第一个被抢占的vCPU;