文章摘要
作者在将网站服务器从Ubuntu迁移到FreeBSD后,发现内存使用报告存在差异。经研究,这是因为操作系统会将磁盘数据缓存到内存以提升性能,但缓存会在需要时释放,导致内存使用率看起来偏高。
文章总结
好的,这是根据您的要求,对原文进行中文重述和精简后的版本:
标题:FreeBSD 吃掉了我的内存!
核心问题:为什么系统报告的内存使用量看起来不对劲?
上个月我分享了将网站服务器从 Ubuntu 迁移到 FreeBSD 的经历。有读者注意到,我展示的 fastfetch 和 btop 两个工具报告的内存使用率差异巨大。这促使我深入探究了现代操作系统内存报告为何如此复杂。
简单来说,内存使用量看起来异常,是因为操作系统会尽可能多地将磁盘数据缓存到内存中,以提升整体性能。这部分缓存是易失的,当系统需要更多内存时会被释放。如果你想了解更详细的原理,请继续阅读。
内存使用量为何难以定义?
“Linux ate my RAM” 网站的核心观点是:未使用的 RAM 就是浪费的 RAM。就像 CPU 缓存会缓存内存内容一样,内存也会缓存磁盘数据以改善用户体验。
现代操作系统都拥有虚拟内存(VM)系统。它将物理内存划分为通常为 4KiB 的“页”,并将这些页放入不同的队列进行管理。例如,当系统发现某些已分配但使用不频繁的内存时,会将其标记为可交换到磁盘(Swap),以便在需要时为其他进程腾出空间。
FreeBSD 的页面队列类型包括: - 活跃 (active):正在被用户进程积极使用的页面。 - 非活跃 (inactive):一段时间未被访问的页面。 - 待清理 (laundry):准备写入交换空间的页面。 - 锁定 (wired):内核自身使用的、不受 VM 管理的页面,以及部分不可交换的内存。 - 空闲 (free):完全未使用的内存。
问题在于,非活跃队列中的内存是可回收的,当系统需要更多内存时,内核会将其释放。而锁定队列中的磁盘缓存部分也是可回收的。因此,准确判断“已用”和“空闲”内存变得非常困难。
磁盘缓存
FreeBSD 默认的 ZFS 文件系统拥有 ARC(自适应替换缓存),这是一个专门用于缓存最近访问数据的系统,能显著提升读取性能。当系统需要更多内存时,ARC 缓存会自动缩小。这部分缓存的大小可以通过 sysctl kstat.zfs.misc.arcstats 查看。
为什么 fastfetch 和 btop 报告的结果不同?
这两个工具(以及 htop 等)都采用不同的启发式算法来决定什么是“已用内存”,这正是差异的根源。
fastfetch的算法是:空闲内存 = 空闲 + 非活跃 + 缓存,已用内存 = 总内存 - 空闲内存。在我的测试中,它报告内存使用了 82%。btop的算法是:可用内存 = 总内存 - 活跃 - 锁定,已用内存 = 活跃 + 锁定。它报告内存仅使用了 7%。htop的算法是:已用内存 = 锁定 + 活跃 + 待清理。它报告使用了 4.49G/5.69G。
btop 在 FreeBSD 上的内存报告存在严重错误
深入 btop 的源代码后,我发现两个问题:
- 整数溢出:
btop使用 32 位无符号整数(u_int)来存储内存字节数。当内存超过 4GiB 时,这个值会溢出并回绕,导致报告的内存使用量远低于实际值。 - 缓存报告为空:
btop通过vm.stats.vm.v_cache_count这个系统参数来获取缓存大小。但自 FreeBSD 12.0 起,这个参数就只是一个“为了兼容性而存在的虚拟参数”,其值始终为 0。因此,btop的“缓存”一栏始终为空。
修复方案
我为此提交了一个修复补丁(PR),主要改动包括:
- 将存储内存字节数的变量从 32 位提升为 64 位,解决溢出问题。
- 不再使用无效的 v_cache_count,而是通过 vfs.bufspace(FreeBSD 自身的文件系统元数据缓存)和 kstat.zfs.misc.arcstats.size(ZFS ARC 缓存)来正确计算可回收的缓存大小。
- 从“锁定”内存中减去 ARC 缓存的大小,以更准确地反映实际被占用的内存。
fastfetch 的情况
fastfetch 也存在同样的问题。我提交的补丁被关闭了,但随后项目维护者以更完善的方式实现了相同的逻辑,不仅修复了 FreeBSD,还让 Linux、SunOS 和 NetBSD 等系统也能正确检测 ARC 缓存。
结论
经过一个月的深入研究,我不仅理解了 FreeBSD 虚拟内存的运作机制,还为 htop、btop 和 fastfetch 这三个重要项目提交了修复补丁。这个过程让我对操作系统有了更深的认识,也让我重温了年轻时对操作系统设计的热情。
评论总结
根据评论内容,主要观点和论据如下:
观点一:FreeBSD与Linux的内存管理差异 - 评论1(jmclnx)指出FreeBSD的swap使用逻辑曾优于Linux,询问现状是否仍如此。 - 评论2(naturalmovement)认为用户因不熟悉ZFS缓存机制而惊讶,强调这是企业级文件系统的正常行为。
观点二:对FreeBSD现状的评论 - 评论5(shevy-java)表示Linux用户立场,认为FreeBSD作为替代方案的道路愈发艰难。 - 评论7(efxhoy)对修复合并表示赞赏,暗示FreeBSD社区仍在积极改进。
观点三:对内存报告机制的质疑 - 评论8(drdexebtjl)质疑使用启发式方法判断内存使用,认为系统应精确知道内存分配,而非依赖估算。
观点四:其他无关评论 - 评论3(m463)提及学生是否保留教材,与主题无关。 - 评论4(duendefm)感谢高质量帖子。 - 评论6(tiffanyh)推荐相关文章。
平衡性总结:评论呈现对FreeBSD内存管理的不同看法,既有肯定其历史优势(评论1),也有批评用户认知不足(评论2),同时指出其当前挑战(评论5)和社区努力(评论7)。对内存报告机制的质疑(评论8)则指向技术细节问题。