内存与 OOM58 条

kswapd 回收线程排查

kswapd0 负责后台回收;持续高 CPU 说明内存压力大或水位配置导致长期回收,应结合回收计数与 PSI 判断而非直接调参。

kswapd 是什么

kswapd0(每个 NUMA 节点一个)是内核的内存回收线程:当某个 zone 的空闲页降到低水位时被唤醒,扫描 LRU 链表回收页缓存与可换出的匿名页,回到高水位后停止。它属于后台异步回收,正常状态下 CPU 占用很低;如果它长期占用可观 CPU,说明内存压力持续存在,需要判断是工作集超出内存、缓存膨胀,还是水位设置让回收发生得过于频繁。

基本信息

线程形态kswapd0,每 NUMA 节点一个(多节点会看到多个)
观察命令ps -eo pid,pcpu,psr,comm | grep kswapd
回收计数/proc/vmstat 的 pgscan_kswapd 与 pgsteal_kswapd
压力视图/proc/pressure/memory
水位参考/proc/zoneinfo 的 min/low/high
同类线程kcompactd 负责内存整理,职责与回收不同

典型使用场景

  • 判断内存是否长期吃紧:kswapd 持续占 CPU 且回收计数快速增长
  • 区分后台回收与直接回收:后者发生在分配路径上,对延迟影响更大
  • 排查缓存膨胀造成的反复回收:结合 workingset_refault 看是否在做无用功
  • 核对水位参数是否过于激进:调大水位会让回收更早、更频繁发生
  • 与 PSI 联合量化内存压力对业务停顿的实际贡献

采样与判读

采样与判读
ps -eo pid,pcpu,psr,comm | grep kswapd  # 回收线程的 CPU 占用与所在核
ps -o pid,ni,comm -C kswapd0  # 确认其 nice 值,理解它与业务线程的抢占关系
grep -E 'pgscan_kswapd|pgsteal_kswapd|pgscan_direct|pgsteal_direct' /proc/vmstat  # 后台与直接回收计数
cat /proc/pressure/memory  # 内存压力视图,判断停顿比例
awk '/Node/{n=$2} /pages free|low|high/{print n, $0}' /proc/zoneinfo | head  # 各节点空闲页与水位
ps -eo pid,pcpu,comm --sort=-pcpu | head  # 先排除其他高 CPU 进程的干扰

关联指标

指标含义判读要点
kswapd CPU后台回收占用的算力长期偏高说明回收是常态而非常态事件
pgscan_kswapd后台扫描页数(累计)增速反映回收工作量
pgsteal_kswapd后台成功回收页数(累计)与扫描量之比反映效率
pgscan_direct直接回收扫描页数增长比后台回收更值得警惕
memory some/full内存停顿比例full 持续增长说明已影响全局
调大水位参数只会让回收更早、更频繁地发生,并不能减少内存需求。应先确认工作集是否真的超出物理内存,或页缓存是否被反复回收,再考虑动参数。
在多 NUMA 节点的机器上要分节点看:单个节点的空闲页长期偏低就足以持续唤醒该节点的回收线程,而整机汇总数据可能看起来还很宽松。

易错点

  • 把 kswapd 高占用当成故障直接调参:根因通常是工作集超出内存或存在内存泄漏
  • 忽略直接回收:allocstall 与 pgscan_direct 增长意味着回收压在分配路径上,对延迟影响远大于后台回收
  • 用单次采样判断压力:所有回收计数都是累计值,必须做差分与趋势观察
  • 不区分缓存与匿名页:缓存可回收、匿名页换出代价高,两者的回收含义完全不同
  • 整机汇总下结论:多节点机器上局部紧张会被平均掉,应按节点核对空闲页与水位

数据来源与参考

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