c++服务端频繁被swap out主因是内核swappiness默认值60过高,导致内存使用率超70%时即倾向换出匿名页,引发毫秒级访问延迟;推荐设为1以保留应急swap能力又避免主动换出,并配合cgroup内存限制与mlock锁关键内存。

为什么C++服务端会频繁被Swap out
不是你的代码写得慢,而是Linux内核在“帮倒忙”。swappiness默认值是60,意味着只要内存使用率一过70%,内核就倾向把进程的匿名页(比如new出来的对象、堆上缓存、STL容器数据)往Swap里推。对C++服务端来说,这很致命:一次std::vector::resize可能触发几十MB内存分配,刚建好的热数据立刻被换出,下次访问就是毫秒级延迟——而你还在等数据库响应。
怎么查当前swappiness是否在拖后腿
别猜,直接看:
-
cat /proc/sys/vm/swappiness—— 查当前值 -
free -h—— 看Swap列有没有持续增长 -
grep -i "pgpgin\|pgpgout" /proc/vmstat——pgpgout数值每秒涨几百,说明正在疯狂换出
重点注意:swappiness=0 ≠ 禁用Swap,它只是告诉内核“除非OOM,否则别动我的匿名页”;而swappiness=1才是更安全的兜底选择——保留Swap应急能力,又几乎不主动换出。
生产环境C++服务端推荐设置
直接执行(需root):
sudo sysctl vm.swappiness=1 echo 'vm.swappiness=1' | sudo tee -a /etc/sysctl.conf
这不是拍脑袋定的数字。理由很实在:
- C++服务端通常有明确的内存上限(比如用
ulimit -v或cgroup限制),不会无节制吃内存 - 它的热数据集中在堆和TLB友好的内存块里,换出再换入的成本远高于让部分请求稍慢一点
- 比起Swap延迟,OOM Killer杀掉整个服务进程更不可接受
如果你用了systemd管理服务,还可以加一行MemoryLimit=到service文件里,和swappiness=1形成双重保险。
调完swappiness还要防什么坑
很多人改完就以为万事大吉,结果发现cc1plus编译时还是卡死,或者gRPC连接突然超时。这是因为:
-
swappiness只管匿名页,不管页缓存(page cache)。dd if=/dev/zero of=/tmp/big bs=1M count=2000这种操作照样能挤爆内存 - 某些C++库(如Boost.Iostreams)内部用
mmap(MAP_ANONYMOUS)分配内存,这部分仍受swappiness影响,但调试器看不到它在top里的RSS里 - 云服务器(如AWS EC2、阿里云ECS)的底层虚拟化层可能有自己的内存回收逻辑,
swappiness=1只能约束Guest OS,不能绕过Hypervisor
真正要稳住,得把swappiness调低 + 用cgroup v2硬限内存 + 在代码里用mlock()锁住关键小内存块(比如TLS session cache),三者缺一不可。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











