CentOS 中 swapper 与内存泄漏的关系
概念澄清
- swapper在 Linux/ CentOS 里通常指内核的交换/回收子系统,核心工作由内核线程kswapd承担:当内存跌破水位线(HIGH/LOW/MIN)时触发后台回收,必要时进行换出(匿名页写入 Swap),并在缺页时换入。它不是用户进程,不会“泄漏”内存;其职责是管理页面回收与置换策略(如 LRU/Clock 等)。因此,出现“swapper 占用高”的现象,多数是系统在回收/换页,而非 swapper 本身有泄漏。
典型关联路径
- 应用存在内存泄漏(堆/匿名页持续增长)→ 系统可用内存被长期占用 → 触发 kswapd 回收与换出 → Swap 使用率上升、可能出现si/so(换入/换出)持续非零,并伴随访问被换出页时的major page fault风暴,表现为“物理内存看似有空闲但很卡”。这类表现常被误以为“swapper 导致内存泄漏”,实则是泄漏引发回收与换页的结果。
- 非泄漏场景也可能看到 swapper 繁忙:例如swappiness 偏高、水位线被调低、一次性大内存分配/突发负载、或文件读写导致 PageCache 挤压(内核更倾向于丢弃 PageCache 而非换出匿名页,因此 PageCache 变化通常不直接推高 Swap)。这些情况下,Swap 升高是策略或负载所致,并非应用泄漏。
如何快速判断是“泄漏”还是“回收/策略”
- 看全局指标
free -h、/proc/meminfo 的 AnonPages(匿名页)是否持续增长;SwapCached 是否同步增加(换出后又被访问)。
vmstat 1 观察 si/so:持续大于200 页/秒且 AnonPages 缩小,多为“积极换出/换入”。
top/htop 查看进程 RES 与 SWAP 列,定位哪些进程被换出较多。
- 定位具体进程
- 按进程汇总 Swap 使用:
sudo sh -c 'for i in /proc/[0-9]*; do pid=${i##*/}; if [ "$pid" -gt 100 ]; then awk -v pid="$pid" "/Swap:/{a+=$2} END {if (a>0) print pid, a/1024 \"M\"}' /proc/"$pid"/smaps 2>/dev/null; fi; done | sort -k2nr | head'。
- 结合
pmap -x <PID>、/proc/<PID>/status 的 VmSwap 字段,确认单进程 Swap 占用。
- 判断换入风暴
perf top -p <PID> 若 page_fault 占比高,说明大量major fault导致换入阻塞,常与随机访问被换出页有关。
- 结论导向
- 若匿名页长期单向增长且对应进程 VmSwap 同步走高,基本可判定为应用侧内存泄漏;若 AnonPages 稳定而 PageCache 主导波动,多为缓存/策略问题。
处置与优化建议
- 先治本:修复泄漏
- C/C++:用 Valgrind、AddressSanitizer 跑压测定位未释放与越界;
- Java:用 jstat 观察 Old 区、jmap dump + MAT 分析 GC Root;
- 修复后,Swap 使用往往断崖式下降。
- 再控源:降低换出倾向与回收压力
- 适度降低 vm.swappiness(如设为10),减少匿名页换出;
- 启用 zswap(内核内压缩匿名页,再决定是否落盘),可显著减少实际落盘量;
- 对关键/非关键进程设置 /proc//oom_score_adj,避免同归于尽。
- 监控与告警
- 建议基线:匿名页占比 > 60% 且持续增长、major fault > 100/s 持续 5 分钟、单进程 VmSwap > 500MB 触发告警。