内存回收水位
内核为每个内存区(zone)维护三条水位:min、low、high。空闲内存降到 low 以下时唤醒 kswapd 后台回收,降到 min 以下则触发直接回收——申请内存的任务自己去回收,表现为延迟飙升。vm.watermark_scale_factor 决定 low 与 high 相对 min 的间距,换算方式是「该 zone 管理的内存 × factor ÷ 10000」,默认 10 即 0.1%。调大等于提前回收,为紧急情况预留更多缓冲。
基本信息
| 参数名 | vm.watermark_scale_factor |
|---|---|
| 默认值 | 10(即 0.1%) |
| 换算方式 | 间距 = zone 管理内存 × factor ÷ 10000 |
| 配合参数 | vm.min_free_kbytes 决定 min 水位的底线 |
| 观察文件 | /proc/zoneinfo 的 pages free 与 min、low、high |
典型使用场景
- 出现直接回收导致延迟毛刺(allocstall 增长)
- 大内存机器上默认间距偏小,后台回收跟不上
- 调整前后对比 zoneinfo 的水位与空闲页变化
- 与 min_free_kbytes 一起规划整体回收策略
- 复盘「内存看似充足却频繁回收」的现象
查看水位
查看水位
sysctl vm.watermark_scale_factor vm.min_free_kbytes
grep -E 'zone|pages free|min|low|high|managed' /proc/zoneinfo | head -30
sysctl -w vm.watermark_scale_factor=50 # 放大间距,回收更提前
cat /proc/vmstat | grep -E 'pgscan|pgsteal' # 回收相关计数
cat /proc/vmstat | grep -E 'allocstall' # 直接回收计数
cat /proc/meminfo | grep -E 'MemFree|MemAvailable'三条水位读法
| 水位 | 含义 | 触及后的行为 |
|---|---|---|
| min | 最低保留水位 | 低于此值触发直接回收,任务同步等待 |
| low | 后台回收水位 | 低于此值唤醒 kswapd 后台回收 |
| high | 回收停止水位 | 高于此值 kswapd 停止工作 |
| 间距 | low 与 high 之间的距离 | 由 watermark_scale_factor 决定 |
调大相当于给系统留更多备用内存:可用内存变少、后台回收更频繁,但直接回收与延迟毛刺的概率会下降。
水位与页大小绑定,判读 zoneinfo 时数值单位是页而不是字节,不能只看 MemFree 下结论。
调整后的影响链条
- 水位抬高后 kswapd 更早开始后台回收,直接回收次数随之下降
- 直接回收减少会改善内存分配路径上的延迟毛刺,延迟分布更平滑
- 代价是可用内存减少、后台回收更频繁,CPU 占用略有上升
- 大内存机器上效果更明显,小内存机器需要更保守地调整
是否需要调整的判据是直接回收计数的增长与延迟毛刺的时间相关性,而不是空闲内存的数字大小。