排查swap导致的日志“诡异耗时”,关键先验证系统是否真在换页:用vmstat 1 5查si/so是否持续非零(si>50 kb/s即可疑),结合sar -b看pgmajfault≥1/秒、/proc/vmstat中pgpgin增量突增,并与日志时间戳对齐sar -w和dmesg确认相关性。

排查因内存页交换(swap)导致的日志中“诡异真实耗时”,关键不是看日志里写了多久,而是要确认那段耗时是否真的由页面换入/换出引发——因为日志打点时间差可能掩盖了底层内存调度的延迟。这类问题常见于服务响应变慢、GC停顿异常、I/O等待飙升但CPU和内存占用表象“正常”的场景。
查清系统是否真在频繁换页
先跳过应用日志,直接验证操作系统级换页行为:
- 运行
vmstat 1 5,重点观察 si(swap-in,每秒从磁盘读入内存的KB数)和 so(swap-out,每秒写入磁盘的KB数);若连续多行非零(尤其 si > 50 KB/s),说明当前正经历实质性换页压力 - 执行
grep -E "pgpgin|pgpgout" /proc/vmstat,查看累计换页总量;再隔10秒重复一次,计算差值——若 pgpgin 增量显著,说明有大量缺页需从swap调入,这会直接拖慢进程执行 - 用
sar -B 1 5查看 pgmajfault(主缺页次数):每次主缺页若需从swap加载,就会引入毫秒级延迟,且无法被缓存加速
定位具体是哪个进程在触发换页
换页不是全局平均发生的,而是由个别进程的内存访问模式驱动:
- 在
top中按 M 排序,关注 %MEM 高且 VIRT 远大于 RES 的进程(VIRT大表示申请了大量虚拟内存,RES小说明实际驻留少,极易触发换页) - 对可疑进程,执行
cat /proc/[PID]/status | grep -E "VmSize|VmRSS|MMUPageSize",比对 VmSize(虚拟内存大小)与 VmRSS(实际物理内存)差距;若相差数倍以上,且该进程恰好处于你日志耗时对应的线程中,高度可疑 - 用
pidstat -r -p [PID] 1观察其 minflt(次缺页)和 majflt(主缺页)实时速率;若 majflt 持续 ≥ 1/秒,就说明它每秒都在从swap加载页面,耗时自然不可控
结合日志上下文做交叉验证
把系统指标和日志时间戳对齐,才能确认“耗时”是否真是换页所致:
- 记录日志中高耗时事件发生的确切时间(精确到秒,如
2026-05-23T07:42:18) - 回查该时刻前后30秒的
sar -W(swap使用率)和sar -B(换页统计)输出;若 %swpused > 70% 且 pgpgin 突增,则强相关 - 检查同一时段
dmesg -T | grep -i "out of memory\|kill process",确认是否有 OOM killer 干预痕迹——哪怕没杀进程,内核回收压力也会抬高换页延迟
区分“假耗时”和“真换页延迟”
有些日志耗时长,其实和swap无关:
- 如果
free -h中 available 仍充足(例如 > 2 GB),而 swap used = 0,那耗时大概率来自锁竞争、网络超时或磁盘I/O,不用查swap - 如果
cat /proc/swaps显示 swap 分区已禁用(空输出),却在vmstat中看到 so/si 非零——这是异常,说明内核在用 zram 或 cgroup memory swap,需查/sys/fs/cgroup/memory/下对应组的memory.memsw.usage_in_bytes - Java 应用中若
jstat -gc [PID]显示 GC 耗时飙升但survivor区未满,同时vmstat有高频 so,很可能是堆外内存(如 DirectByteBuffer)触发了系统级换页,而非JVM堆内GC











