背景

vmpressure 用回收的 scan:reclaim 比值推断内存压力:扫描了很多页却没回收到几个,就认为系统吃紧。一旦判定有压力,它会施加 socket pressure,让 TCP 收紧接收窗口、节流网络吞吐。这个机制对 order-0 与低阶回收是合理的:扫得多收得少,确实像是内存不够。

┌─────────────────────────────────┐
│  高阶分配在碎片化系统触发回收   │
└────────────────┬────────────────┘
                 ▼
┌─────────────────────────────────┐
│    扫描多、回收少,比值难看     │  但系统其实有大量空闲,差效率只怪碎片
└────────────────┬────────────────┘
                 ▼
┌─────────────────────────────────┐
│ vmpressure 据此断言 socket 压力 │  TCP 被不必要地节流,接收窗口卡死
└─────────────────────────────────┘

但高阶(costly order,超过 PAGE_ALLOC_COSTLY_ORDER)分配是另一回事。它主要靠 compaction 整理出连续页才成功,而不是靠 reclaim。在碎片化的系统上,高阶回收天然"扫描多、回收少":那些页正在被用、不该释放,差效率反映的是碎片,不是内存压力。可旧 vmpressure 不区分 order,照样拿这个难看的比值去断言 socket pressure,于是明明系统还有大把空闲内存,TCP 却被无谓节流。

问题

  • vmpressure 不区分 order,scan:reclaim 比值差就断言 socket pressure
  • 高阶回收依赖compaction,碎片化时天然扫描多回收少
  • 这种差效率被误判为内存压力
  • TCP 被不必要节流,接收窗口卡在最小值

方案

核心是给 vmpressure 加上 order 维度,让它认清"高阶回收的差效率不代表压力"。

旧:所有 order 都判压力
┌────────────────────────────────┐
│  回收效率差就断言 socket 压力  │
└───────────────┬────────────────┘
                ▼
┌────────────────────────────────┐
│ 高阶回收的天然低效也被当成压力 │
└────────────────────────────────┘

新:costly order 跳过 socket 压力
┌──────────────────────────────────────┐
│    只在低阶回收时断言 socket 压力    │
└──────────────────┬───────────────────┘
                   ▼
┌──────────────────────────────────────┐
│ 高阶回收依赖compaction,差效率不再误 │
│ 判                                   │  memcg 回收与低优先级关键压力不受影响
└──────────────────────────────────────┘

具体地,通过 scan_control 把 order 传进 vmpressure 既有调用点,socket pressure 只在 order <= PAGE_ALLOC_COSTLY_ORDER 时才断言。costly order 的回收本就交给 compaction,它的低效 reclaim 不再触发对 TCP 的节流。

两处要保住不受影响:

  • memcg 回收(try_to_free_mem_cgroup_pages 恒为 order 0)无条件通过过滤
  • vmpressure_prio 在内部调 vmpressure 时显式传 order 0,确保来自低回收优先级的关键 pressure 不会被 order 过滤误伤

收益

本 patch 由生产环境一例 net throughput 受损驱动。在一台受影响主机上(~15GB available、零 cgroup 压力、buddyinfo 显示 order 0-3 充足但 order 7+ 为 0,即碎片化),bpf 采集显示 94% 的 vmpressure 调用来自 order-7 kswapd 回收。TCP minimum recv window 阈值为 rcv_ssthresh:19712。

该主机 live-patching 前后的 TCP 连接收窗口状态:

状态 卡在 minimum recv window 的连接
Before 723 / 3,843(19%)
After(live-patch 后约 30 分钟) 0 / 3,470

错误触发的 socket pressure 被消除,TCP 不再被无谓节流,受影响连接的接收窗口恢复正常。

需说明:这是单一受影响主机的 live-patching before/after,不是 A/B fleet 对比;数据反映的是该碎片化场景下 order-7 回收误节流 TCP 的修正。