LWN: 用DMEMFS来更高效地管理部分内存!

关注了就能看到更多这么棒的文章哦~

Sidestepping kernel memory management with DMEMFS

By Jonathan Corbet
December 7, 2020
DeepL assisted translation
https://lwn.net/Articles/839216/

内核的主要工作之一就是管理系统所拥有的内存。不过多年来,出于各种原因,有时候需要把系统一部分内存隐藏起来,让内核看不到。现在又出来一个最新的原因,来自一个叫做 DMEMFS 的机制,提出这个机制是希望绕过内核跟踪 RAM 过程中的一些低效率做法。

从前,人们把内存隐藏起来让内核看不到,主要是为了避免内存碎片化的相关问题。在系统运行一段时间后,几乎不可能分配得出大块连续区域,这就给那些必须要这种大块连续内存的 device 带来了麻烦。当时,有一个叫做 "bigphysarea "的 patch,一直没有合入 kernel,主要就是用来为这种大块连续的内存分配来预先 reserve 一块内存区域。由于内核没有直接接触到这些内存,所以它无法对其进行操作,也就不会有碎片化问题。LWN 第一次介绍 bigphysarea 是在 1999 年,但当时这个 patch 已经存在一段时间了。

后来(2010 年),contiguous memory allocator(CMA)patch 使用同样的技术提供了类似的功能。不过从那时起,分配大块连续区域的需求已经变小了很多。内核本身的碎片整理机制已经有了很大的改进,并且大多数设备也都安装了更多的内存。CMA 现在依靠 compaction 机制(https://lwn.net/Articles/486301/) ,不再预先挖掉一块内存保留下来专用了。

DMEMFS 的动机则不同。内核通过一个叫做 "memory map" 的数据结构来跟踪内存,它本质上是一组 page strcuture 的数组。有大量信息放在这个结构中,用来告知内核每个 page 是如何使用的、跟踪它在各种 list 中的位置、也用来将它与真正的 backing store 对应起来,等等。多年来,我们已经花费了很多努力来保持 struct page 尽可能的小,但在 64 位系统中,它仍然占据了 64 个字节。

这个 size 看起来似乎并不是很大,但是,一般的 page 本身大小仅仅为 4KB,在现代的系统中,会有很多的 struct page。一台安装了 16GB 的笔记本电脑会有 4194304 个页面,也就是说,光是跟踪这些内存就用了 256MB 的内存。在笔记本上损失这么多内存或许是可以忍受的,但在其他一些环境下,就无法接受了。在 patch 相关的邮件中,作者 Yulei Zhang 指出,一个提供虚拟主机托管的服务商(hosting provider),如果一台机器安装了 320GB 的内存,就会因为 page structure 而损失 5GB 的内存。如果能够回收这些内存,服务提供商就可以将更多的 guest 塞进这台机器,增加每台服务器带来的收入,而这个指标是托管提供商非常重视的。

如上所述,DMEMFS 的工作原理是在启动时分出一部分系统内存,具体数量由 dmem= 这样的命令行参数控制。系统中每个 NUMA 节点上都需要按照这个指定数值来预留相应的内存。如果这个数量以"!"开头,意思就反过来,相当于指定 DMEMFS 要给内核留多少内存,而把其余的内存都分给 DMEMFS。一旦系统启动,可以通过挂载 dmemfs 文件系统并创建若干个(一个也行)所需大小的文件来分配这部分内存。调用 mmap() 来把内存映射到进程的地址空间。一个 dmemfs 文件也可以交给 QEMU 作为 guest machine 的内存空间(backing store)。这块内存区域也支持 NUMA policy,也可以提供 huge page,用起来就跟普通内存一样。

也许对于那些迫切需要充分利用内存、而且不需要内核来实际管理内存的场景来说,DMEMFS 是最好的解决方案。但这是一个由 37 个 patch 组成的改动,增加了 3400 多行代码,专门用于把内存资源管理这个工作从 kernel 中切割出来。每当出现这样巨大改动的情况时,都应该思考一下问题的根源,以及是否可能存在其他的解决方案。

早在 1991 年,当第一个 Linux 内核发布的时候,当时的机器内存比现在还少。当初的这个 PC 广告 (https://books.google.com/books?id=WVAEAAAAMBAJ&lpg=PA1&dq=infoworld&pg=PT73&hl=en#v=onepage&q&f=false) 很有启发意义,一个高端系统的特点是 4MB 的内存,价格仅为 3700 元,这是 1991 年。该系统使用了 4KB 的页面,所以总共有 1024 个页面供内核管理。当时大多数个人电脑系统的内存都比这个少。

当代的计算机内存空间已经相当大了,但 page size 仍然是 4KB,所以内核管理的 page 数量增加了三个数量级了。page struct 的数量也相应增加了。这些 struct 自己也变大了,主要是因为向 64 位处理器过渡导致 struct page 的大小大幅增加。很明显,size 增加会带来副作用,但是与此同时,page structure 的数量增加也导致内核中许多地方的开销变大。

一个可能的解决方法是增加内核管理的 page size,如果需要的话,可以将多个物理页面聚集成较大的一组来作为管理单位。现在一些架构也支持使用更大的 page size,例如 arm64 内核可以使用 64KB 的页面大小。多年来,许多开发者试图在内核中实现某种通用的页面集群(generalized page clustering),但这些工作都没能进入 mainline。没有合入的原因之一是这些改动都比较复杂,但这不是唯一的因素。

使用更大的 page size 会导致的另一个问题就是内部碎片,从而只需要使用少量内存的时候,由于必须分配一个完整的 page 从而导致浪费内存。一个典型的例子就是小文件所对应的 page cache。一个单行的 shell 脚本可能只需要不到 100 个字节,但它仍然需要在 page cache 中分配一个完整的 page。超过这 100 个字节的区域都被浪费了,使用的 page size 越大,显然浪费的就会越多。几十年前的大家的经验都是:Unix 系统上的大多数文件都很小。虽然现在这个说法可能不像以前那样典型了。

编者不知道有没有什么研究是认真地测量了真实世界的系统上如果使用更大的 page size 的话,因为 internal fragmentation 而会导致损失多少内存,但这种担心使得这类 patch 无论如何也很难被接受并合并入 mainline。目前,最接近的工作可能是 Matthew Wilcox 的 "large pages in the page cache" ,这个工作是在更高层次实现的,并不会减少系统中 page struct 的数量。

因此,DMEMFS 的补丁可能需要合并,原因很简单,现在这组 patch 已经能正常工作了。但很可能这个问题的真正解决方案并不是这组 patch。与其从内核中隐藏页面,不如通过以更大块的方式来处理内存来减少内核内部的开销。目前看来,不断增加的内存大小最终会迫使人们做出这种改变。而事实证明,这么多年来内存大小一直在不断增长。在改变内核以更有效的方式处理内存之前,我们可能别无选择,只能合入这类将 kernel 排除在内存分配决策之外的改动了。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

1.何为内存模块 (Memory Module)? 内存模块是指一个印刷电路板表面上有镶嵌数个记忆体芯片chips,而这内存芯片通常是DRAM芯片,但近来系统设计也有使用快取隐藏式芯片镶嵌在内存模块上内存模块是安装在PC 的主机板上的专用插槽(Slot)上镶嵌在Module上DRAM芯片(chips)的数量和个别芯片(chips)的容量,是决定内存模块的设计的主要因素。 2.什么是Parity? 早先所使用的存储器数据检错方式是Parity Check,其是以每8比特增加1比特的方式进行检错。因此若是具备Parity的存储器,其数据宽度将比非parity的存储器为大。不过若以 Parity的检错方式看,其多出的奇偶位事实上只用于分辨奇数或偶数个比特数。这种方式仅能得知是某一位发生错误,并无法确定是哪一个位置发生错误,而且无法运用在双数位的检错上。 3.什么是ECC? ECC是另一种为进步的存储器数据检错机制。其工作的方式与Parity不同,并不是采用单一比特的方式来进行检错,而是采用数据块(block)概念与复杂的演算方法来修正数据。因此不仅能检测多位比特错误,还能进行修正单一比特的错误。 4.SPD的作用是什么? 为Serial Presence Detect 的缩写,它是烧录在EEPROM内的码,以往开机时BIOS必须侦测memory,但有了SPD就不必再去作侦测的动作,而由BIOS直接读取 SPD取得内存的相关资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值