脏页速率限制
dirty limit 即脏页产生速率上限,是 QEMU 8.1 引入的能力。 它使用基于 KVM dirty ring 的新算法,在热迁移期间限制客户机运行速度。
算法框架如下:
------------------------------------------------------------------------------
main --------------> throttle thread ------------> PREPARE(1) <--------
thread \ | |
\ | |
\ V |
-\ CALCULATE(2) |
\ | |
\ | |
\ V |
\ SET PENALTY(3) -----
-\ |
\ |
\ V
-> virtual CPU thread -------> ACCEPT PENALTY(4)
------------------------------------------------------------------------------
首次调用 QMP 命令 qmp_set_vcpu_dirty_limit 时,QEMU 主线程启动节流线程。 节流线程随后循环执行三个步骤:
PREPARE (1)
PREPARE (1) 为 CALCULATE (2) 准备数据,包括虚拟机的脏页速率及其上限。 速率通过 KVM dirty ring 计算,该机制告诉 QEMU, 自上次 KVM_EXIT_DIRTY_RING_FULL 异常以来虚拟 CPU 产生了多少脏页。 上限由调用者指定,可直接取得。
CALCULATE (2)
为各虚拟 CPU 计算适当休眠时间,确定其节流惩罚。 计算需要谨慎,使脏页速率逐渐降至上限而不振荡。 为此提供两种策略:当前速率离上限较远时,按速率与上限的比例增减休眠时间; 接近上限时,增减固定时间。
SET PENALTY (3)
根据 CALCULATE (2) 的结果,为需要节流的各虚拟 CPU 设置休眠时间。
完成三个阶段后,节流线程回到 PREPARE (1),直到达到脏页速率限制。
各虚拟 CPU 线程在 KVM_EXIT_DIRTY_RING_FULL 异常处理路径中读取并执行休眠, 即 ACCEPT PENALTY (4)。执行写入进程的虚拟 CPU 会退出到此路径并受到节流, 执行读取进程的虚拟 CPU 则不会。
借助 KVM dirty ring,该算法按需限制虚拟 CPU,使脏页速率保持在上限内。 这能让热迁移期间的读取性能更稳定,并有助于改善大型客户机的响应速度。