朋友把博客服务器从跑了十年的 Ubuntu 16.04 换成 FreeBSD,装好之后照例跑一遍 fastfetch 看状态,结果吓了一跳:同一台机器,fastfetch 说内存用了 82%,切到 btop 一看,只有 7%。差了十倍不止,两个工具盯着的明明是同一份物理内存。这条围观评论后来被顶上 Hacker News,有人提醒说 fastfetch 的数字可能才是对的——这句话把他拖进了一个连续几周的兔子洞:"用了多少内存"这个看起来最基础的问题,在 FreeBSD 上压根没有唯一答案。

一台机器,两套算法,两个答案

三个工具,三种算法:fastfetchfree+inactive+cache当"空闲",算出来已用 82%;btopactive+wired当"已用",算出来只有 7%;htop 用 wired+active+laundry,落在 79% 左右,反而跟 fastfetch 更接近。没有谁在撒谎,只是各自挑了不同的启发式去定义"已用",而 FreeBSD 比 Linux 多切了一刀。

同一时刻,两套算法两个答案 fastfetch 空闲 = free+inactive+cache 已用 = 总量 − 空闲 82% 与htop结果接近 btop 已用 = active + wired 可用 = 总量 − active − wired 7% 后文揭晓:算错了

内存不是二分的,是五个抽屉

FreeBSD 内核把物理内存按 4KiB 分页,再扔进不同队列。进程正在用的叫 active;一段时间没被碰过,挪去 inactive;系统缺内存时,把 inactive 页面搬进 laundry,准备写入 swap;等程序再要这块数据,又从磁盘捞回 inactive、最终回到 active。真正干净没人用的,才是 free

wired 是内核锁死、不能换出的部分,但这里边混进去一大块 ZFS ARC 缓存——本质上它跟 Linux 的磁盘缓存一样,是可以随时收缩腾出来的,只是被记在了"锁死"这一栏。用 sysctl kstat.zfs.misc.arcstats.size 能单独把这块揪出来,配合 c_min/c_max 还能看到它的伸缩上下限。

内存的五个抽屉 active — 正在被进程使用 inactive — 一段时间没被访问 laundry — 排队等写入swap wired — 内核锁定,不可换出 其中ARC缓存,其实可回收 free — 纯粹空闲,随时可用

btop 错在哪:一个溢出的整数,一个装死的计数器

对从 Linux 转过来的运维,这一坑最容易踩。翻 btop 源码会发现,它把 active、wired 的字节数存进 32 位无符号整型 u_int,上限是 4,294,967,295,而 4GiB 换算成字节是 4,294,967,296——只差 1。一旦两块内存加起来的字节数跨过这条线,数字直接从头绕回来,7% 就是这么算出来的假象。

只差1字节,内存腰斩 u_int 存储上限 4,294,967,295 4GiB 对应字节数 4,294,967,296 超过这一位,计数直接归零重来

更离谱的是"cached"那一栏。btop 读的是 vm.stats.vm.v_cache_count 这个 sysctl,而这个页队列从 FreeBSD 6.3.0 起就已经不存在,12.0 之后这个接口干脆被标注成"Dummy for compatibility"——问就是 0,永远是 0。ARC 这块本该单独展示的缓存,就这样在 btop 的账本里彻底消失,跟前面的整数溢出叠在一起,把已用内存拉得离谱地低。


别拿Linux的free去套FreeBSD

Linux 用户习惯盯 MemAvailable,FreeBSD 压根没有对应字段,它的 free/inactive/wired 划分方式跟 Linux 不是一回事。拿两边的 free 对 free、used 对 used,本身就是错的方法论——这也是为什么"Linux吃内存,缓存无害"这套老科普,不能原样搬到 FreeBSD 服务器的监控面板上。

  • 提醒.也别把"缓存都能瞬间无成本回收"当真。ARC 收缩涉及元数据结构调整,极端情况下确实可能来不及腾地方,造成短暂的延迟抖动,不是绝对零代价。

真正该盯的不是某个静态数字,而是压力信号:swap 的读写有没有持续在跑、laundry 队列是不是一直往上堆、页面扫描率有没有异常升高。这些动起来了,才说明内存真的紧张;free 数字低、wired 数字高,大概率只是缓存在干它该干的活。

数字没错,错的是拿数字当结论。

原文本身写到 ARC 怎么把 wired 撑大就戛然而止,fastfetchbtop 两套算法到底该信谁、这篇会不会有续篇,都还没个准信。但有一件事已经能先记住:下次看到 FreeBSD 服务器"内存告急",别急着扩容——swap 有没有真的在动,才是那道分水岭。