首页/系统/Linux 内核与性能调优速查/vm.watermark_scale_factor 回收水位间距
内存与 OOM58 条

vm.watermark_scale_factor 回收水位间距

决定 kswapd 提前回收的积极程度:各 zone 的 low 与 high 水位间距按内存规模乘以该系数(默认 10 即 0.1%),调大让回收更超前。

内存回收水位

内核为每个内存区(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 占用略有上升
  • 大内存机器上效果更明显,小内存机器需要更保守地调整
是否需要调整的判据是直接回收计数的增长与延迟毛刺的时间相关性,而不是空闲内存的数字大小。

易错点

  • 只看 MemFree 判断内存是否充足:真正决定回收行为的是各 zone 的水位与压力
  • 把 factor 当百分比直接累加:换算要乘以 zone 管理内存再除以 10000
  • 调得过大:长期多留备用内存,可用内存减少且回收更频繁
  • 忽略页大小:zoneinfo 的数值单位是页,按字节理解会差出数倍
  • 只调这一个参数:回收行为还与 min_free_kbytes、脏页阈值共同作用

数据来源与参考

  • Linux 内核 Documentation/admin-guide/sysctl/vm.rst
  • Linux 内核 Documentation/admin-guide/mm/concepts.rst
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌