我有一台 8GB 的迷你主机(N100,NVMe 512G),平时跑 Docker 和 Node 编译。
有次 free -m 看到 buff/cache 5.6G、available 只剩 1.1G,我就按网上教程 sync; echo 3 > /proc/sys/vm/drop_caches。
结果缓存掉了,编译从 3 分 20 秒变成 4 分 05 秒,因为依赖包又得从磁盘重新读。
后来我才盯住 grep MemAvailable /proc/meminfo,这个值才是应用还能拿多少内存;buff/cache 里大部分是可回收页缓存,不是“被吃掉了”。
我的观点很直接:清缓存是拿 I/O 换心理安慰,先看 available 再决定要不要动 swap。
swap 我建议留,但别乱关。
创建 2G swapfile 的步骤:fallocate -l 2G /swapfile、chmod 600 /swapfile、mkswap /swapfile、swapon /swapfile,然后在 /etc/fstab 加 /swapfile none swap sw 0 0。
vm.swappiness=0 在 5.0 以后不是“禁用 swap”,只是尽量不用;真到内存压力大时照样换出,反而容易卡顿,我一般设 10,vm.vfs_cache_pressure=50。
对比一下:swap 分区稳定但改大小麻烦,swapfile 灵活但 ext4 上可能碎片化,btrfs 上要先 chattr +C /swapfile 再 fallocate。
如果你用 NVMe,2G swapfile 足够救急;机械盘就别把 swappiness 调高,不然编译时风扇和延迟一起上来。
小内存机器我更推荐 zram。
8GB 内存可以配 4G zram,算法用 zstd:modprobe zram,zramctl --find --size 4G --algorithm zstd,mkswap /dev/zram0,swapon -p 100 /dev/zram0。
实测压缩比大概 2.5:1 到 3:1,lz4 更快但压缩比低,zstd 压缩比高但 CPU 多 10% 到 15%;树莓派 4B 这种 ARM 盒子我用 lz4,N100 用 zstd。
我的独立观点:zram 不是“内存变多”,而是拿 CPU 换内存,CPU 弱的机器别贪大,设物理内存的 50% 就行。
对比 swapfile,zram 没有磁盘 I/O,但断电就丢;所以我是 zram 4G 做第一层,2G swapfile 做第二层。
OOM 别只看 dmesg | grep -i oom,用 journalctl -k -T | grep -i 'out of memory' 能看到具体哪个进程被 kill。
Ubuntu 22.04 默认启用了 systemd-oomd,systemctl status systemd-oomd 可以确认;配置在 /etc/systemd/oomd.conf,用户会话在 /etc/systemd/system/user@.service.d/oomd.conf 里设 ManagedOOMMemoryPressure=kill 和 ManagedOOMMemoryPressureLimit=80%。
对比 earlyoom,systemd-oomd 更贴近 cgroup v2,但规则不透明,我第一次被它杀掉 VS Code 远程会话时查了半小时日志。
更该做的是限制容器:Docker 用 --memory=2g --memory-swap=3g,cgroup v2 下看 cat /sys/fs/cgroup/memory.max。
OOM killer 不是敌人,是最后保险;真正要管的是 cgroup 的 memory.high,让进程先被限速而不是直接被杀。
最后给个我自己的顺序:先 free -m 看 available,再配 4G zram,然后留 2G swapfile,最后给 Docker 加内存上限。
我把 swappiness 从 60 调到 10 后,同一台机器编译内存峰值从 7.6G 降到 6.1G 可用,编译时间只多 3 秒,但不再触发 OOM。
别背“swap 有害论”,也别迷信 drop_caches;内核的页缓存和 zram 都是工具,关键看你的瓶颈是内存、CPU 还是磁盘 I/O。
如果你只有 4GB 内存,zram 设 2G、算法 lz4、swappiness 设 20,比加 8G swap 分区更实际。
这些数字不是标准答案,是我这台 N100 上跑出来的;你可以在自己的机器上用 zramctl 和 vmstat 1 复测。