compaction 腾高阶页
迁移已用页
free scanner 找目标
batch 上限 32 页
compact_gap(order)
watermark 之上加 headroom
给迁移目标预留空间
两个启发式共用
回收与适合性
free scanner
COMPACT_CLUSTER_MAX
单批最多 32 页
凑够 batch 就停
实际工作集有限
headroom 应反映
scanner 的真实容量
而不是阶算值
旧:2 << order
order-0: 2 页
order-4: 32 页
order-9: 1024 页
随阶指数增长
每升一阶翻倍
高阶 headroom 很大
与 scanner 容量脱节
order-9 过度 32 倍
scanner 只有 32 页
COMPACT_CLUSTER_MAX = 32
free scanner 工作集
凑够 batch 就停
实际只需 32 页
公式默认 scanner
要处理 2 << order 页
与真实容量不符
碎片化生产主机
64GB Instagram 主机
43 台未打补丁
kswapd 追求虚高 gap
18% 达标
kswapd 尝试达到 gap
仅 18% 的尝试
多数情况继续回收
低阶空闲页被忽视
46% 假性失败
order-9 适合性检查
46% 假性失败
zone 其实够 scanner
却过不了虚高门槛
不是没内存
是门槛算错
适合性被误判
cap 到 32 页
min(2UL << order, COMPACT_CLUSTER_MAX)
只改一道最小值
order 5+ 才封顶
compact_gap()
min(2UL << order, COMPACT_CLUSTER_MAX)
order 0-4 原值 <= 32
order 5+ 取 32
低阶行为不变
headroom 落地
对齐 scanner 容量
不再按阶无限涨
两个启发式共用
高阶不再过度预留
低阶行为不变
高阶不再过度预留
cap 只动 order 5+
__compaction_suitable()
watermark + headroom
判断 zone 是否值得压
headroom 虚高 → 不适合
旧:门槛过高
order-9 空闲页够 scanner
不够 watermark + 1024
compaction 被推迟
适合性假性失败
新:门槛落地
headroom 最多 32
够 scanner 就放行
compaction 更早启动
同一批空闲页
同一批空闲页
判断结果翻转
门槛回到真实容量
kswapd 高阶回收
追求 order 的高阶页
看 reclaim 与 gap
reclaim 不够就继续
旧:死磕高阶
order-9 gap = 1024
reclaim 未到 gap 不降
高阶需求拖延
高阶仍压在 kswapd
新:更早降级
gap <= 32
reclaim 达到 gap
sc->order = 0
高阶交给 kcompactd
降级不是放弃
是把高阶交给 kcompactd
回收与压缩分工
相似 workload · mm-new
3 次 60s run
未打补丁 vs 已打补丁
降级次数均值 0 → 28
THP fallback
thp_fault_fallback
1217 → 738
缺页回退减少
高阶分配更顺
kswapd 扫描
pgscan 6328 → 3773
pgsteal 5657 → 3243
扫描与回收都降
headroom 收窄的结果
降级不是退化
高阶交给 kcompactd
kswapd 更早收手
Instagram A/B
v6.13 / 64GB / 60s
43 台未打 / 59 台已打
pgscan ~1.6M → ~449K
效率与成功率
reclaim 83.8% → 91.0%
compaction 2.1% → 28.3%
THP 4.9% → 17.2%
forced lru_add_drain ~107K → ~64K
收益链
headroom 对齐容量
回收少做无用功
compaction 更早启动
数据来自生产 A/B
扫描量降约 70%
compaction 成功率大幅升
数字来自生产 A/B
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x