背景

虚拟化场景下,free page reporting 让 guest 把 buddy 中的空闲页周期性地报告给 host,host 据此取消这些页的映射(unmap),从而把物理内存归还给 host 侧其他任务。reporting 由一个 delayed work 驱动,旧实现的报告间隔硬编码为 2 * HZ(约 2 秒)。

固定 2 秒在稳定 workload 下是合理的:既较快把空闲内存归还 host,又不至于过于频繁。但在 spiky 的分配/释放波动(churn)下问题显现:guest 刚报告出去的页被 host unmap,紧接着 guest 又重新分配这些页,host 不得不重新建立嵌套页表映射,触发大量 nested page fault,反而造成性能损失。

┌──────────────────────┐
│     guest 空闲页     │
└──────────┬───────────┘
           ▼
┌──────────────────────┐
│ 固定 2 秒报告给 host │
└──────────┬───────────┘
           ▼
┌──────────────────────┐
│  host unmap 这些页   │
└──────────┬───────────┘
           ▼
┌──────────────────────┐
│ guest 重分配已报告页 │  触发 nested page fault
└──────────────────────┘

问题

  • 报告间隔硬编码为 2HZ,无法按 guest workload 调整。
  • spiky 分配释放下,激进立即报告让 host 反复 unmap 又重建映射。
  • guest 重用已报告页触发大量 nested page fault,开销显著。
  • 缺少在激进回收与低开销之间权衡的旋钮。

方案

把这个硬编码间隔暴露为一个可调的模块参数 page_reporting_delay_ms,单位毫秒,默认 2000(精确等于原先的 2 * HZ),默认行为完全不变,只是新增了调节能力。

它通过 module_param() 以 uint 类型导出,路径是 /sys/module/page_reporting/parameters/page_reporting_delay_ms,命名与内核变量一致。delayed work 的调度由原来的固定 PAGE_REPORTING_DELAY 改为 msecs_to_jiffies(page_reporting_delay_ms) 动态换算,覆盖 __page_reporting_request() 与 page_reporting_process() 两处调度点,并在 kernel-parameters.txt 里登记为 page_reporting.page_reporting_delay_ms= 引导参数。

管理员可按 workload 选择:内存长期闲置时调小以尽快归还 host,churn 剧烈时调大以在更长窗口内批量报告,吸收分配与释放的波动,避免 hypercall 与 re-fault 的反复开销。参数不封顶,取 0 也安全:上报只由 high-order 页释放触发,hypercall 开销进入前有 slot 容量水位检查把关。

上报间隔改为可调的模块参数
┌────────────────────────────────────────────────────┐
│ 把硬编码的 2 HZ 间隔暴露为 page_reporting_delay_ms │
│ 模块参数                                           │
└─────────────────────────┬──────────────────────────┘
                          ▼
┌────────────────────────────────────────────────────┐
│ 默认 2000 毫秒与原行为一致,管理员可               │
│ 按 workload 调整                                   │
└─────────────────────────┬──────────────────────────┘
                          ▼
┌────────────────────────────────────────────────────┐
│ churn 剧烈时调大在更长窗口批量上报吸               │
│ 收波动                                             │
└────────────────────────────────────────────────────┘

收益

作者未提供性能数据,从代码逻辑推断的预期收益:

  • churn 场景下调大延迟,在更长窗口批量报告空闲页,减少 guest 重用已报告页导致的 nested page fault。
  • 降低报告频次,摊薄每次报告的 hypercall 与 host 侧 re-fault 开销。
  • 默认 2000ms 与原 2HZ 行为一致,无回归风险,仅在需要时按 workload 调整。
  • 作为模块参数无取值上限,管理员可自由按 workload 设定上报节奏。