要确认 swap 的是 anon page 还是 file-backed page,需结合 /proc/vmstat 中的 pswpin/pswpout 与 /proc/*/smaps 的 Swap 字段,并用 pmap -x 观察 ANON 和 SWAP 列是否同步增长:若 ANON 高且 SWAP 同步上升,则为 anon page 被 swap。
怎么确认 swap 的到底是 anon page 还是 file-backed page
Linux 的 swappiness 只影响内核在内存压力下「倾向」换出哪类页,但不禁止换出任何一类。所以即使设成 swappiness=10,swap 仍可能高频发生——关键得先分清:到底是谁在被 swap?
用 /proc/vmstat 最直接:pgpgin/pgpgout 是 I/O 页计数,不区分类型;真正要看的是 pgmajfault 和 /proc/*/smaps 中的 Swap 字段,但更高效的是:
- 运行
cat /proc/vmstat | grep -E "pgpg|pgmaj|pgpg",重点看pswpin和pswpout(单位:页),这两个是纯 swap I/O 计数 - 查具体进程:用
awk '/^Swap:/ {sum += $2} END {print sum}' /proc/*/smaps 2>/dev/null | sort -n | tail -5,结果是每个进程当前占用的 swap 页数(KB) - 结合
pmap -x看某进程的ANON列(匿名映射)和SWAP列是否同步增长——如果ANON高且SWAP也高,基本就是 anon page 在被 swap
为什么 swappiness=10 还会大量 swap anon page
swappiness 不是开关,而是权重调节器:它控制的是「在 reclaim 时,从 anon list 和 file list 中按比例选择候选页」。当系统真的缺内存,且 anon pages 占比极高(比如 Java 堆、大 malloc 缓存),哪怕权重低,reclaim 也必须扫到它们。
- 典型场景:Java 应用堆设了
-Xmx8g,但物理内存只剩 2G 可用,此时无论swappiness是 1 还是 100,内核都得把部分 anon page 换出 -
swappiness=0才是「尽量不 swap anon」,但它不等于「禁止」,仅表示:只有在 file cache 几乎清空后,才考虑 anon;而swappiness=10仍会给 anon 分配约 10% 的回收机会 - 注意:如果
/proc/sys/vm/swapiness显示为 10,但/proc/sys/vm/overcommit_memory是 2(严格模式),且/proc/sys/vm/overcommit_ratio设得太小,也会导致 malloc 失败前被迫提前 swap
file-backed page 被 swap 的常见诱因
file-backed page(如 mmap 的普通文件、共享库)本不该常驻 swap,因为它们有磁盘源,可直接丢弃或重读。但以下情况会让它们进 swap: