关注了就能看到更多这么棒的文章哦~
Jonathan Corbet
Gemini translation
原文链接:https://lwn.net/Articles/1060967/
多代 LRU (Multi-Generational LRU,简称 MGLRU) 是一种替代性的 内存管理 (memory-management) 算法,于 2022 年底合并入 6.1 内核 (kernel)。它曾承诺带来大幅的性能提升和更简洁的代码。然而,自那时起,MGLRU 的进展便陷入停滞,且在许多系统中仍未启用。随着 2026 年 Linux 存储、文件系统、内存管理与 BPF 峰会 (LSFMM+BPF) 的临近,多位内存管理开发者表示希望讨论 MGLRU 的未来。虽然一些开发者正在寻找改进该子系统的方法,但另一位开发者则呼吁将其彻底移除。
MGLRU 温故知新
内核必须处理的核心内存管理任务之一,是确定哪些页面应保留在内存中,哪些页面应被换出到较慢的存储设备中(即“回收 (reclaim)”)。通常,最佳策略是保留近期最可能被使用的页面,同时回收那些不再被使用的页面。鉴于预测未来充满挑战,内核必须高度依赖有关页面近期使用情况的信息,作为后续操作的指南。 最近最少使用 (Least-recently-used,简称 LRU) 列表便是该解决方案的关键组成部分。
内核中经典(且目前仍是默认)的解决方案依赖于两类 LRU 列表(更准确地说,是多对类似的列表),分别被称为“活跃 (active)”和“非活跃 (inactive)”列表。被认为当前正在使用的页面应保留在活跃列表中,而那些看似未被使用的页面则进入非活跃列表。当需要回收页面以供他用时,系统会查阅非活跃列表以寻找潜在的牺牲品。该方案的大部分复杂性(以及许多启发式算法)都集中在如何正确设置这两个列表的大小,并决定何时将页面从一个列表移动到另一个列表。
MGLRU 将这种方法扩展到了多个列表,称之为“代 (generations)”。在列表的一端,最年轻的一代包含已知(或至少被认为)在不久前被使用过的页面。每一代较老的列表则追踪那些比前几代空闲时间更长的页面。各种类型的访问会将页面从较老的代移动到较年轻的代;当需要更多空闲内存时,内核会从最老的一代开始搜刮。据称,MGLRU 能更准确地识别真正的冷页面,并在执行该工作时消耗更少的 CPU 时间。关于 MGLRU 设计的更多信息,请参阅 这篇 2021 年的文章。
MGLRU 的困扰
近期的讨论表明,MGLRU 并未完全兑现其所有承诺。这一切始于 2 月中旬,当时 Zicheng Wang 发起了 一项关于 LSFMM+BPF 讨论 MGLRU 的请求,特别是关于它在 Android 上的表现。Wang 表示,尽管 MGLRU 已进入内核多年,但许多 Android 系统供应商并未启用它。有多个问题影响了这一决定。
其中一个抱怨(后来也得到了其他人的响应)是 MGLRU 无法正确平衡 匿名页 (anonymous pages) 和 文件后端页 (file-backed pages) 之间的回收。传统的 LRU 为每种页面类型维护单独的一对列表(因此有了前文关于“多对”LRU 列表的评论——此外还有其他复杂情况)。这两组列表的回收通常略微偏向文件后端页,因为它们通常不需要写回持久存储;长期存在的 swappiness sysctl 调节开关 可用于调整内核攻击每个列表的激进程度。
Wang 指出,在启用 MGLRU 的情况下,匿名页往往停留在最年轻的两代中,导致它们永远不会被回收(进而导致文件后端页被过度激进地回收)。调整 swappiness 开关并不能解决这个问题。Wang 的雇主(一家名为“荣耀”的 Android OEM 厂商)通过显式使用内存控制组来强制回收非前台应用的匿名页,但在 主线 (mainline) 内核中尚无通用解决方案。同样 提议开设 MGLRU 专题会议 的 Kairui Song 也提到了匿名页回收的问题。
Wang 还有许多其他问题待讨论。MGLRU 可能会在任何给定的控制组中回收过于激进,释放超出所需数量的内存。在低端设备上,尤其是在可回收页面不多的情况下,它的开销太大了。此外,Android 对热应用和冷应用的定义(旨在优先处理用户当前正在交互的应用)与 MGLRU 之间存在脱节,而 MGLRU(与内核其他部分一样)缺乏这种区分。其中一些问题已通过供应商特定的补丁 (hacks) 得到解决;例如,存在 一个供应商钩子 可以豁免当前前台任务免受回收。Wang 希望讨论这些供应商修改中的哪些(如果有的话)应该进入主线内核。
Barry Song 提出了 另一个单独的抱怨:当系统执行 预读 (readahead)(投机性地读取它认为用户空间可能很快请求的数据)时,它会将所有生成的页面放入最年轻的一代,即使并不能保证这些页面一定会被使用。这可能导致实际正在使用的页面被回收,而预读页面却留在内存中。相比之下,传统的 LRU 会将这些页面放入非活跃列表,如果没有再次被引用,它们会相对较快地被回收。至少这个问题应该可以通过一个相对简单的方案来解决。
Kairui Song 提出的问题清单侧重点有所不同,首先是 MGLRU 使用了三个 页面标志 (page flags)。这些标志 长期处于短缺状态;试图分配哪怕一个标志的补丁往往都会遭遇强烈抵制。增加 MGLRU 管理的代数的想法也意味着需要使用更多的页面标志。他提议将这些标志移至别处,使系统支持多达 63 代,同时释放 MGLRU 当前使用的三个页面标志。
另一个问题是某些工作负载的性能倒退(尽管其他工作负载表现更好)。Kairui Song 认为这些问题源于 MGLRU 中管理回收的控制循环,可以通过更好地追踪文件后端页的使用历史来解决。然而,这样做需要三个页面标志,大概就是那些通过将代数移至别处刚刚释放出来的标志。
他表示,MGLRU 提供的指标在许多方面与传统 LRU 不同,这使得系统其他部分更难理解任何给定页面的内存管理状态。他提议改变页面状态的追踪方式以改善这种状况。Kalesh Singh 也 描述了指标方面的问题,称这两种 LRU 实现之间的差异巨大,这给 Android 用户空间 内存不足 (Out-of-memory,简称 OOM) 守护程序等组件带来了困难。
顺便提一下,Kairui Song 还提到了增加一个 BPF 钩子的想法,以便自定义页面代放置的决策。
虽然还提到了其他问题,但或许令人惊讶的是,大多数参与者都忽略了另一个相关议题:内核中原本就存在两种竞争的 LRU 实现。Kairui Song 确实注意到,他描述的问题是“MGLRU 仍不是内核中唯一 LRU 实现的诸多原因”之一。David Rientjes 补充说,讨论应涵盖“需要解决哪些问题,才能让 MGLRU 走上成为默认实现的道路,从而消除两种独立的实现”。这将是一项艰巨的任务;某些工作负载在一种实现下的表现肯定总会优于另一种,因此移除其中一种必然会导致某些工作负载性能下降。将这些倒退降低到可接受的水平尚需时日。
索性移除它?
内核开发者(事实上也是许多项目中的开发者)长期存在一种担忧:某个开发者增加了一堆复杂的代码,然后就不再负责维护了。Matthew Wilcox 断言 这种情况正发生在 MGLRU 身上:
在我看来,MGLRU 最大的问题是 Google 把它丢给我们后就跑了。 提交 44958000bada 声称它现在已有人维护,并增加了三名维护者。在该提交之后的六个月里,这三个人在
mm/目录下没有任何提交!这种状况简直令人汗颜。我说,把它拔掉吧。
MGLRU 的原始开发者 Yu Zhao,正如上述提交中所注,目前已“转向其他项目”。从(仅限订阅者的) Zhao 的 KSDB 页面 可以看到,他偶尔会改进 MGLRU,但最后一次是 6.14 内核中的几个提交。虽然据说有其他开发者在处理这些代码,但自那以后,被添加到 MAINTAINERS 文件中的人都没有对 MGLRU 进行过任何更改。
因此,在某种程度上,MGLRU 被贡献给内核后不久便遭遗弃是事实。作为 MGLRU 指定维护者之一的 Axel Rasmussen 似乎同意 这一评估,但他表示情况很快就会改变:
我承认这是一个大问题。我们在这方面辜负了社区,我们计划从 4 月份开始纠正这一局面,例如通过与 Kairui 及其他人合作来解决悬而未决的问题。
缺乏开发者持续的关注,无疑让 MGLRU 难以克服许多潜在用户遇到的问题。即便如此,移除它的想法几乎没有得到支持。Barry Song 请求保留它,以便解决这些问题:
它只需要更多的工作。MGLRU 在设计上有许多亮点,包括使用更多的“代”来区分冷热页面、通过利用缓存局部性来减少扫描开销的环顾机制,以及最小化锁持有的数据结构设计。
Gregory Price 列举了 MGLRU 的一系列已知问题。不过,他也并未要求将其彻底移出内核。
因此,5 月份 LSFMM+BPF 上的 MGLRU 讨论似乎不太可能把时间花在彻底移除它的想法上。但人们将非常有兴趣了解需要做哪些工作才能将 MGLRU 提升到所需的性能水平,并或许在某一天成为内核中唯一的 LRU 实现。如果一些开发者愿意承诺承担这些工作,MGLRU 最终可能会取得过去几年一直缺失的进展。这看起来将是一场有趣的会议。
LWN 评论概述:
评论区反映了用户对 MGLRU 的复杂态度。一方面,有用户表示在内存极度超售的服务器上,启用 MGLRU 后系统响应更具预测性,显著改善了 SSH 登录和服务的稳定性;另一方面,讨论也集中在技术细节上,如与 ZFS ARC 的对比,以及经典 LRU 如何通过影子列表 (shadow tracking) 为交换后端页面提供工作集保护。同时,也有观点认为 MGLRU 在未解决特定工作负载下的回收平衡和调优问题前,尚不具备全面替代传统双列表机制的条件。
全文完LWN 文章遵循 CC BY-SA 4.0 许可协议。
欢迎分享、转载及基于现有协议再创作~
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~
516

被折叠的 条评论
为什么被折叠?



