LWN:让swap机制现代化:引入 swap table

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

Jonathan Corbet
 Gemini translation
 原文链接:https://lwn.net/Articles/1056405/ 

内核的交换子系统(swap subsystem)是一个复杂且经常被冷落的庞然大物。它也是内存管理子系统(memory-management subsystem)中的关键组件,对整个系统的性能有着重大影响。在 2025 年 Linux 存储、文件系统、内存管理和 BPF 峰会上,Kairui Song 概述了一项简化并优化内核交换代码的计划。这项工作的第一部分是在 Chris Li 的帮助下完成的,并已在 6.18 版本的主线(mainline)中合并。本文将跟进 6.18 版本的工作,为未来审视尚未合并的变更奠定基础。 

在虚拟内存系统中,内存短缺必须通过回收 RAM 来解决,如有必要,还需将其内容写入适当的持久化后端存储(backing store)。对于文件支持的内存(file-backed memory),文件本身就是该后端存储。然而,匿名内存(anonymous memory)—— 即持有进程使用的变量和数据结构的内存 —— 缺乏这种天然的后端存储。这就是交换子系统的用武之地:它提供了一个在匿名页所占据的内存被其他用途所需时,用来写入这些页面的地方。交换允许将未使用(或很少使用)的页面推送到较慢的存储中,从而使系统的 RAM 能够用于当前正在使用的数据。 

交换子系统简要入门

关于内核交换子系统的完整描述确实会非常冗长;其中包含大量的复杂性,其中大部分是随着时间的推移而积累起来的。以下是对 6.17 内核中交换子系统样貌的部分且简化的概述,可作为理解后续变更的基础。 

交换子系统使用一个或多个交换文件,这些文件可以是存储设备上的分区,也可以是文件系统中的普通文件。在内核内部,活跃的交换文件由 struct swap_info_struct 描述,但通常使用简单的整数索引来引用。每个文件被划分为页面大小的槽位(slots);内核交换区域中的任何给定槽位都可以使用 swp_entry_t 类型来标识: 

●●●
..typedef.struct.{
....unsigned long.val;
..}.swp_entry_t;

这个 long 值被分为两个字段:高 6 位是交换文件的索引号(为了更清晰起见,在交换代码中被称为“类型”),其余部分是文件内的槽位号。有一组简单的函数用于创建交换条目并获取相关信息。 

请注意,上述描述的是与架构无关的交换条目形式;每个架构还将拥有一个用于页表条目的架构相关版本。好奇的读者可以查看在两种格式之间进行转换的 x86_64 宏。然而,在交换子系统本身内部,使用的是架构无关版本的交换条目。 

对交换过程的一个过于简化的描述大致如下:当内存管理子系统决定回收一个匿名页时,它会选择一个交换槽位,将页面的内容写入该槽位,然后将关联的交换条目存储在页表条目中(使用架构相关格式),并清除“存在(present)”位。下一次尝试引用该页面时将导致缺页异常(page fault);内核将看到交换条目,分配一个新页面,从交换文件中读取内容,然后相应地更新页表条目。 

事实真相是事情要比这复杂得多。例如,将页面写入交换文件需要时间,并且在写入完成之前页面本身不能被回收。因此,当做出回收决策时,页面会被放入交换缓存(swap cache),在许多方面,这类似于用于文件支持页面的页面缓存(page cache)。说一个页面在交换缓存中实际上只意味着已经分配了一个交换条目;页面本身可能仍然驻留在 RAM 中,也可能不在。如果在写入过程正在进行时该页面发生缺页异常,尽管该页面位于交换缓存中,也可以快速将其重新激活。 

所有这一切意味着交换子系统必须跟踪交换缓存中每个页面的状态,而该状态不仅仅涉及分配的交换槽位。为此,在 6.18 之前的内核中,交换子系统维护了一个名为 swapper_spaces 的数组,其中包含指向 address_space(地址空间)结构数组的指针。该结构用于维护地址空间(文件的字节,或交换文件的槽位)与支持该空间的存储之间的映射。它提供了一组可用于在 RAM 和后端存储之间移动页面的操作。使用 struct address_space 意味着,除其他外,许多处理页面缓存的代码也可以操作交换缓存。 

使用 struct address_space 的另一个原因是与其关联的 XArray 数据结构。对于交换文件,该数据结构包含文件中每个槽位的当前状态,状态可以是以下任一: 

  • 槽位为空。

  • 有一个页面分配给了该槽位,但该页面也驻留在 RAM 中;在这种情况下,XArray 条目是一个指向页面(更准确地说,是包含该页面的 folio)本身的指针。

  • 有一个页面被分配了,但它仅存在于交换文件中。在这种情况下,该条目包含“影子(shadow)”信息,内存管理系统利用这些信息来检测那些在被交换出后很快又被调入的页面。(有关此机制的概述,请参阅 2012 年的这篇文章)。

更有趣的是,并非每个交换文件只有一个 address_space 结构和 XArray。相反,文件被划分为 64MB 的块,并为每个块创建一个单独的 address_space 结构。这种设计有助于将交换条目的管理分散到多个 XArray 中,从而在发生大量交换的大型系统上减少竞争并提高可扩展性。因此,交换文件的 swapper_spaces 条目指向一个 address_space 结构数组;例如,一个 1GB 的交换文件将由一个包含 16 个此类结构的数组来管理。 

在管理交换槽位方面还有一个复杂之处(就本次讨论而言——其实还有很多其他复杂之处)。每个交换设备还被划分为一组交换簇(swap clusters),由 struct swap_cluster_info 表示;这些簇的大小通常为 2MB。交换簇使交换文件的管理更具可扩展性;系统中的每个 CPU 都维护一个分配给它的交换簇缓存。关联的交换条目随后可以完全在 CPU 本地进行管理,仅在必须分配或释放簇时才需要跨 CPU 访问。交换簇减少了处理交换条目时扫描全局交换图(swap map)的工作量,但仍必须使用适当的 XArray 来获取或修改给定槽位的状态。 

交换表(swap table)

有了这些背景知识,我们就可以审视针对 6.18 版本所做的更改了。这些更改始于这样一个认知:处理交换条目的交换子系统代码已经可以访问这些条目所属的交换簇。将状态信息保留在簇中将允许消除 XArray,取而代之的是简单的交换条目 C 数组。交换簇更细的粒度有助于进一步实现交换条目管理的局部化,从而提高可扩展性。 

因此,第一阶段补丁集扩充了 swap_cluster_info 结构;6.17 之后版本的该结构包含一个新的数组指针: 

●●●
..atomic_long_t.__rcu *table;

新的 table 数组在大多数架构上被设计为恰好占据一个页面,它是动态分配的,在交换文件未满时减少了交换子系统的内存使用。表中的每个条目都是上面看到的相同 swp_entry_t 值,描述了交换缓存中一个页面的状态。交换代码已经重构以使用这种新组织方式,许多内部 API 只需要最小的改动或根本无需改动。覆盖每 64MB 的 address_space 结构数组已经消失;不再需要 XArray,并且地址空间操作可以由一个名为 swap_space 的单一结构提供。 

总之,内核之前使用两个独立的聚类机制(address_space 结构和交换簇)划分交换区域,现在仅拥有一种聚类方案,这增加了许多交换操作的局部性。根据 Song 的说法,现阶段的最终结果是“在基准测试和工作负载测试中,吞吐量、RPS 或构建时间有高达 5-20% 的性能提升”。这种速度提升完全归功于移除了 XArray 查找,以及由于以更小的块管理交换空间而带来的竞争减少。 

这就是 6.18 版本时的情况。尽管这一变化意义重大,但这仅仅是简化和改进内核交换代码项目的开始。6.19 内核并没有显著推进这项工作,但还有另外两个部分正在考虑中,其中一个似乎已准备好在 7.0 版本中发布。这些变化将在本系列的第二部分中介绍。 

LWN 评论概述:

读者们对内核代码中为了“更清晰起见”而引入新术语的做法报以会心的微笑。许多评论者高度赞扬了这次重构,认为它深入理解了问题本质和现有实现的局限,成功剥离了多年来因低风险补丁累积而成的冗余复杂层,使系统变得既快又简洁。同时也有读者关注动态分配的安全性,询问在内存极度匮乏的情况下,如果无法为新的 table 数组分配空间会发生什么。 

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

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

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

内容概要:本文围绕“基于改进秃鹰算法的微电网群经济优化调度”展开研究,提出了一种改进的秃鹰搜索算法(BES),旨在解决微电网群在复杂运行环境下的多目标、强约束、非线性及高维经济调度问题。通过引入特定优化策略,增强了基础算法的全局搜索能力和收敛效率,克服了传统智能算法易陷入局部最优的缺陷。研究构建了一个包含分布式电源、储能系统与多元负荷的微电网群调度模型,以最小化系统综合运行成本为核心目标,综合考虑功率平衡、设备出力能力、储能运行特性等多重约束条件。通过仿真实验验证了所提算法在调度精度、稳定性和计算效率方面相较于传统方法具有明显优势,并进一步展示了其在降低能源开支、提升可再生能源消纳水平方面的实际应用价值。; 适合人群:具备一定电力系统基础知识或优化算法背景,从事新能源调度、智能优化算法研究与应用等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微电网群、综合能源系统等场景下的经济调度优化;②为秃鹰算法及其他群体智能算法的改进、复现与性能对比提供参考范例;③服务于科研仿真、算法验证及工程化应用需求。; 阅读建议:建议读者结合文中提供的Matlab代码实现进行实践操作,重点关注算法改进机制与调度模型的构建逻辑,同时可借助网盘资源获取完整资料,以加深对算法性能表现与应用场景的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值