脏页速率限制

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,使脏页速率保持在上限内。 这能让热迁移期间的读取性能更稳定,并有助于改善大型客户机的响应速度。