首页/系统/Linux 内核与性能调优速查/直接回收(allocstall)诊断
内存与 OOM58 条

直接回收(allocstall)诊断

分配内存失败时内核在分配路径上同步回收,造成延迟尖峰;allocstall 计数增长即表示发生过直接回收。

直接回收是什么

直接回收发生在内存分配路径上:当某次分配发现水位不足,进程自己必须同步扫描并回收页,回收完成之前无法继续执行。这就是 allocstall 计数增长常与延迟毛刺同时出现的原因——它把回收成本直接加到了业务线程上。与之相对的是 kswapd 的后台回收,由内核线程异步完成,通常不会阻塞业务。

基本信息

核心计数grep allocstall /proc/vmstat(新内核按 zone 细分)
配套计数pgscan_direct、pgsteal_direct
追踪手段perf record -e 'vmscan:*' -ag(需 root 与 perf 支持)
关联指标/proc/pressure/memory 的 full 行、业务延迟毛刺
常见诱因水位不足、高阶分配(大页/驱动 DMA)、NUMA 本地节点紧张
影响面直接体现为分配线程的停顿,对延迟敏感服务危害最大

典型使用场景

  • 排查业务延迟毛刺:把 allocstall 增量与延迟曲线放在同一时间轴对齐
  • 判断是否该抬高水位或增加内存:持续增长说明分配经常走同步回收
  • NUMA 机器上定位本地节点紧张:整机空闲充裕也会频繁触发直接回收
  • 驱动或大页相关的分配问题:高阶分配更依赖连续页,失败路径更长
  • 容量评估:把直接回收的发生频率作为扩容的量化信号之一

确认与追踪

确认与追踪
grep allocstall /proc/vmstat  # 分配路径上的直接回收次数(可能按 zone 细分)
sleep 60  # 隔一分钟再采一次,比较差值才能判断是否持续发生
sudo perf record -e 'vmscan:*' -ag -- sleep 10  # 采集回收相关事件
sudo perf report --stdio | head -20  # 查看直接回收的调用来源
grep -E 'pgscan_direct|pgsteal_direct' /proc/vmstat  # 直接回收的规模与回收量
cat /proc/pressure/memory  # full 行增长与直接回收高度相关
sar -B 1 5  # 看 pgscand/s 与 %vmeff,判断直接回收的速率与效率

关联指标

项目含义判读要点
allocstall分配时被迫直接回收的次数增量频率决定影响程度
pgscan_direct直接回收扫描的页数反映工作量大小
pgsteal_direct直接回收释放的页数与扫描量之比反映回收效率
%vmeff(sar)整体回收效率偏低说明该扩容而不是调参
memory full全局停顿比例持续增长说明影响已扩散
分配路径上的回收代价直接落在业务线程上,因此比后台回收更值得警惕。观察时要按 NUMA 节点看:本地节点不足时,即使整机空闲内存充裕也可能频繁触发直接回收。
偶发一次直接回收并不可怕,关键是频率与业务延迟的相关性。把计数增量与监控中的延迟曲线叠加,如果两者同步出现尖峰,才算建立了因果证据。

易错点

  • 把偶发一次当成持续问题:必须看增量频率与业务延迟的相关性,单点增长没有诊断价值
  • 只看次数不看效率:扫描很多但回收很少时,扩容比继续调参数更有效
  • 忽略 NUMA 局部性:不按节点观察就找不到本地节点不足这一常见原因
  • 用调大水位来掩盖根因:工作集真的超出内存时,调参只能推迟问题发生
  • 不考虑高阶分配的特殊性:大页与驱动类分配对连续页更敏感,更容易触发同步回收

数据来源与参考

  • Linux 内核 Documentation/admin-guide/mm/
  • Linux 内核 mm/vmscan.c
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌