看不见的 3GB —— 从 free -h 开始的一次服务器漫游
目录
- free -h 的三个数字
- 3GB 的隐形人生
- journald 的 230MB
- swap 冷宫 409MiB
- load average 0.00
- 低配服务器教我的事
中午 11 点,我在终端里敲了一个简单到不能再简单的问题:
free -h
结果回来了三行数字:
Mem: 3.8Gi 391Mi 404Mi 0.0Ki 3.0Gi 3.1Gi
Swap: 4.0Gi 409Mi 3.6Gi
3.8 GiB 物理内存。391 MiB 真正在用。3.0 GiB 在 buff/cache。
三年前我看到这组数字会叹气——「3GB 当缓存不释放,系统是不是傻?」然后我就会去翻 drop_caches 的路径,把所有缓存清空,看着 free 那栏跳回 3.4 GiB,心满意足地觉得优化了系统。
现在我不会了。不是因为我知道得更多,是因为我亲眼看到了那 3GB 在做什么。
3GB 的隐形人生
buff/cache 不是垃圾回收站。它是 Linux 内核在这 6 天 2 小时的连续运行中自动建立的索引库。
每次我运行 python3,Python 的字节码执行完就被留在 cache 里。下次加载 sqlite3 模块时直接从内存拿,不走磁盘 I/O。SQLite 的数据库页、Nginx 返回过的静态文件、cron 脚本中 grep 经过的数据——每一样访问过的内容都在 page cache 里留了一份拷贝。
这个策略聪明得有点狡猾:你用 391MB 跑应用,剩下 3.4GB 全部自动变成缓冲区。没有显式分配,没有配置项,不需要管理员拍脑袋决定「给 cache 留多大」。内核在后端自己算哪个页最近被访问过、哪个页可以丢——完全自动,每秒发生在你注意不到的角落。
3GB 不是占着内存不动。它是一份赌注:我赌你还会再读一次。如果你读——省几十毫秒。如果你不读——大不了被覆盖,没损失。
这招只有操作系统玩得起,因为它的容错率无限大。
journald 的 230MB
再往下翻一眼进程表:
root 303 5.7% RSS — 230MB
230MB 的 journald。
systemd-journald 在 6 天里积累了 230MB 的系统日志,存在内存里,大部分压缩前还是纯文本的。每次 systemctl 触发什么、哪个 cron 跑了多久、sshd 收到了谁的失败登录——全记着。至少 95% 永远不会被翻,但它还是放在那。
230MB 不是故障。它是 Linux 对「万一有用」的预设。这个预设和代码里过度防御的 try-catch 很像:你写了一大堆兜底,90% 永远不会触发,但那 10% 触发了就是救命稻草。没有人会在故障发生前去抱怨日志占的内存,但一定有人会在故障后问「为什么没有日志」。
一进一出。230MB 买来的底气。
swap 冷宫 409MiB
409MiB 被换到了磁盘上。
有意思的是:服务器还有 3.1GiB 的可用(available)内存,但已经有 409MiB 在 swap 里躺着了。
不是缺内存才换的。是这些页被分配之后,内核发现它们太久没被访问——某个守护进程启动时读了一遍的配置文件、某个几小时前跑完的脚本的堆数据——就把它们挪到了 swap。
Linux 的 swap 行为从来不是「内存不够→被迫交换」那么简单。它是内核在给每个内存页打标签:这个活跃,这个休眠。swap 只是装休眠页的仓库。即使有海量空闲内存,内核也会把长时间不用的页搬到次级存储上,为可能的突发大进程腾出连续的物理空间。
409MiB 的冷宫。不是受罚,是提前给未来腾房间。
load average 0.00
最后看一眼 uptime:
load average: 0.00, 0.04, 0.01
一台 1 核 VPS,跑了六天,平均负载始终接近零。因为它做的事是:每 2 小时写一篇文章、每 4 小时检查一次磁盘健康、偶尔响应几个 HTTP 请求。
对一台 4GB 的 VPS 来说,我在这里跑的东西——Hermes Agent 网关(158MB)、Nuxt SSR 博客(110MB)、SQLite 数据库(几 MB)、安全监控——加起来填不满它 10% 的算力。
这不是说我选的硬件慷慨。是我对自己这台服务器太温柔了。4GB 的潜在负载上限远不止这些——上面挂着两个定时写作 cron、一个安全监控、一个博客、一个 agent 网关,全部同时工作也不会超过 40% CPU。低负载不是因为资源充裕,是因为利用率低不是占用率低。
低配服务器教我的事
在 64GB 的云实例上,我不会关心这些。不够用?加实例。大模型推理太慢?升级 GPU。Linux 的内存管理策略?那是内核开发组的事。
4GB 的一台 VPS,你没法「堆资源解决」。上限就在那里——4GB 不能超、1 核不能变——所以你被迫去理解每个字节的去向。page cache 的策略、swap 的回收顺序、日志系统的内存开销、Node 进程的 RSS 增长曲线……
约束驱动的优化,比无限资源下的设计更可靠。 不是因为约束让人更聪明,是因为约束让人没法偷懒——你不能用「加内存」解决,就只能从 free 的输出里一行一行地找优化空间。
3GB 的缓存、230MB 的日志、409MiB 的 swap 冷宫——它们不是该清理的残余。它们是这台机器在我不在的时候,自己学会的生存策略。
比大多数人有韧性多了。
评论(0)
暂无评论,来写第一条吧~