RFC-0201:回收客户机内存

RFC-0201:回收客户机虚拟机内存
状态已接受
领域
  • 虚拟化
说明

允许主机使用之前分配和延迟释放的访客虚拟机内存

问题
Gerrit 更改
  • 720508
作者
审核人
提交日期(年-月-日)2022-12-15
审核日期(年-月-日)2022-12-01

总结

允许主机回收客户机使用的内存。

设计初衷

在客户机中运行占用大量内存的应用,并在主机中启动占用大量内存的应用,即使客户机内存不再使用,也可能会导致 OOM。

原因有两个。

  1. 我们目前不允许主机自动从客户机中获取内存。
  2. 我们不支持客户机主动告知主机“以下是未使用的内存页面的列表,如果需要,您可以随时使用这些页面”。

用户体验历程示例

  1. 启动“termina”或 debian 访客
  2. 在客户机中启动一个占用大量内存的应用
  3. 退出客户机中需要占用大量内存的应用
  4. 在主机中启动一个占用大量内存的应用
  5. 观察主机按 OOM 的情况 度假村

背景

操作系统启动时,它会询问硬件(对于客户机而言,是 Hypervisor)有多少物理内存。如果主机告知客户机有 4GiB 的 RAM,那么客户机就会知道它可以分配 100 万左右的 4KiB 页面。

其方法是在客户机操作系统认为的物理地址(称为访客物理地址)与实际物理地址(称为主机物理地址)之间引入一定程度的映射。请注意,地址转换的第一级别是客户机虚拟内存地址与客户机物理地址之间的映射。也就是说,客户机虚拟地址首先由使用客户机操作系统管理的页面表进行转换的硬件转换为客户机物理地址,然后再转换为主机物理地址 - 后一种转换由 Hypervisor 管理的页面表控制。

当访问客户机虚拟到尚未映射的客户机物理地址时,客户机会处理自己的页面错误。Hypervisor 可处理客户机-物理到主机物理转换的页面故障。

我们使用的是分页内存,这意味着当 Hypervisor 为客户机提供 X GiB RAM 时,不会预先分配任何内存,而只会在确实需要这些页面时分配。必需,在这种情况下,访客将尝试访问页面。从 Hypervisor 的角度来看,分配的物理内存页面属于客户机,不能用于主机进程。

因此,客户机最终可能会获得大量已分配的物理内存页面,而这些页面并没有被使用,而主机可能因为内存不足而无法运行自己的进程。

下面我们将介绍向主机提供客户机内存的两种方法:

Virtio 气球

主机可以通过配置目标提示框大小,告知客机 Virtio 提示框驱动程序使用 inflate 将提示框设置为特定大小。膨胀提示框意味着客户机将预留所需数量的内存页,并将已分配内存页的客户机物理地址报告回主机。从此时开始,主机可以取消提交报告的内存页面,并使用会减少所报告内存的物理内存。

如果 VIRTIO_BALLOON_F_DEFLATE_ON_OOM 通过 virtio-气球协商,客户机可以随时再次使用内存。请参阅 Virtio 规范 5.5.6.1。目前,我们会启用 VIRTIO_BALLOON_F_DEFLATE_ON_OOM。

主机可以通过缩小提示框的目标大小,允许访客重复使用提示框中的页面。如果配置的提示框大小小于提示框中的实际页面数,则访客可以重复使用之前提供给提示框的页面。如果客户机想要再次使用内存,则会对提示框执行 deflate 操作,告知主机该客户机将来会使用一系列物理客户地址。当访客访问页面已从提示框中移除后,进行 deflate 之后,它将遇到一个客户机物理页面故障,Hypervisor 将分配新的物理内存页面供客户机使用。

如需详细了解 Virtio Balloon 核心功能,请参阅 Virtio Balloon 幻灯片Virtio Balloon 视频

免费网页报告

2020 年,Virtio-ballon 获得了一项名为“免费网页报告”的新功能。

免费页面报告为访客提供了一种向主机报告可用内存页面的方式。客户机通过向免费页面报告添加大小为 4MiB(Linux 实现常量)的可用页面并向主机发送报告来实现此目的。访客可保证在主机确认报告之前不会重复使用任何可用页面。

主机收到可用页面报告时,会取消将内存页面用于托管应用,并将确认报告发回给客户机。此时,客户机可能会重复使用之前已释放和已确认的页面。如果访客决定重复使用该页面,则主机会检测到用于托管物理页面的访客错误,并分配新的物理页面以满足访客请求。

请参阅免费网页报告:由 Alexander Duyck ( Intel) 撰写。幻灯片 10 了解详细说明。

利益相关方

教员

  • cpu@google.com

审核者

  • abdulla@google.com
  • dahastin@google.com
  • tjdetwiler@google.com

咨询人员

  • cwd@google.com

社交

此 RFC 已经过虚拟化团队的审核。曾与 cwd@google.com 讨论了该方法,对方正在解决类似但更大的 ChromeOS 问题。

设计

目标

  • 在客户机内运行应用后,请回收主机的内存。
  • 应最大限度地降低内存回收对客户机和主机的性能影响。

非目标

  • 平衡多个客户机的高内存用量。
  • 当客户机和主机争用内存时,动态确定应用的优先级。
  • 支持 Fuchsia 客户机的内存回收。

合格标准

  • 在“动机”部分所述的用户体验历程中,Fucchsia 没有达到 OOM。
  • 主机可用内存大致恢复到在客户机中运行需要占用内存的应用之前的位置。
  • 在内存回收之前和之后,客户机可以继续运行需要占用大量内存的应用。
  • 除非主机内存不足,否则访客页面缓存不会受到影响。
  • 至少有一个客户机运行时,主机 OOM 的数量明显减少。

解决方法

  • 使用 virtio_BREAK 气球中的免费网页报告功能来回收可用内存以供主机使用。
  • 在发生“低”和“严重”主机内存压力事件时膨胀 ballon,以清理访客页面缓存并回收碎片化的内存页面。
  • 概念验证确认,免费页面报告确实按预期回收内存。

实现

使用免费的网页报告

我们将使用免费网页报告功能向主机报告并收回所有可用内存。

AllPAGE_REPORTING_MIN_ORDER 或更高顺序的任何数值(在 Linux 内核中定义为 4MiB)。

使用免费页面报告将在接下来的 30 秒内回收大部分内存。报告的可用页面大小为 2MiB 或 4MiB,预计会有一定量的内存碎片。在访客端,免费页面报告会错开时间生成,以尽可能减少对性能的影响。

Linux-5.15 将在 2MiB 和 4MiB 块中报告大多数 30 秒内可用的内存。

免费页面报告不会逐出 Linux 页面缓存,如果客户机正在运行 IO 密集型工作负载,这可能会造成问题。如需了解 Linux 中的页面缓存,请参阅 Linux 页面缓存基础知识

当我们的 Linux 客户机映像开始使用 MGLRU 时,这种情况可能会发生变化。请参阅 MGLRU 的“缺点、替代方案和未知”部分。

不要随意删除页面缓存是件好事,这样做是有原因的。仅当主机确实需要内存时,主机才应该从访客页面缓存中获取内存。这意味着,我们需要提供一种方法,以便在主机面临内存紧张时,回收用于页面缓存的客户机内存。

在主机内存压力时膨胀客机气球

第二项更改是使用 memorypressure 提供程序,在 WARNING 和 CRITIAL 主机内存级别膨胀提示框。

膨胀气球有两个目标:

  • 逐出客户机页面缓存,如果客户机正在执行密集型文件 IO 并填满页面缓存,这一点非常重要。
  • 回收大多数碎片化内存页面,因为提示框膨胀以 4KiB 的粒度完成,而免费页面报告使用的粒度为 4MiB。

膨胀量与可用的客户机内存成正比。当出现 WARNING 和关键主机内存事件时,提示框将膨胀到可用客户机内存的 90%。如果可用内存从“一般”急剧下降为“严重”,我们必须同时膨胀 WARNING 和 CRITIAL 事件。当主机内存压力恢复为“正常”时,提示框将缩小为 0%。

我们希望避免在主机面临内存紧张时不断膨胀和膨胀气球。提示框膨胀会同时影响访客和主机的性能。最重要的是,Intel 指出,不断调整提示框的大小会导致许多 TLB 崩溃

为了防止气球大小来回弹跳,我们会限制气球膨胀操作,使气球每 X 秒膨胀 1 次。X。初始值为 1 分钟。可能会出现更多超时。例如,如果主机长时间处于内存压力状态,超时以约束气球。警告:可以根据 teamfood 测试遥测数据添加额外的超时时间。

性能

当用户在客户机中运行占用大量内存的应用时,实现内存回收可以提高主机内存性能。当客户机具有可回收的可用内存时,主机将有更多可用的内存可用,而不是采用内存压缩和其他占用大量 CPU 资源的方式获取内存。

在 Linux 实现中,免费网页报告操作会错开 30 秒的时间执行,以降低对客户机的性能影响。我们预计内存密集型访客工作负载的性能影响为 1%-2%。请参阅免费网页报告基准

在主机内存不足时膨胀气球,可能会增加主机和客户机的额外负载。

在启用和未启用内存回收功能的情况下,主机在内存紧张下运行时,我们需要衡量客户机“TLB 崩溃”中断的次数。

基准:

要捕获的指标

  • 基准针对检测性能下降而报告的一般指标
  • 基准测试前后客户机和主机中的可用内存
  • 客户机中的 TLB 截球中断

安全注意事项

与 ballon 膨胀一样,回收的免费页面会在终止操作过程中被归零。这样可以防止访客信息泄露给主机和其他访客。

测试

大部分工作将通过单元测试和 2 个集成测试完成。一个集成测试将涵盖报告内存回收的免费页面,另一个集成测试将涵盖访客页面缓存和提示框膨胀的交互。

“动机”部分中所述的用户体验历程将手动进行测试。用户体验历程依赖于访客启动使其变得不封闭。如果我们进行自动化的端到端虚拟化测试,则可以扩展以涵盖此场景。我们认为,依赖于为此 RFC 构建自动化端到端虚拟化测试不现实。

缺点、替代方案和未知情况

多代 LRU 框架

多代 LRU 框架(也称为 MGLRU)是一种针对 Linux 内核的内存改进功能。Linux 中的当前页面回收在 CPU 占用率方面过于昂贵,并且通常对逐出的内容做出明智的选择。MGLRU 旨在提供比当前 Linux 内核页面回收代码更好的选择,并提高实现效率。Google 工程师团队发现,其冷启动时间缩短了高达 16%,同时减少了低内存终止事件;Chrome 操作系统浏览器中的内存不足终止事件减少了 59% 以上,浏览器中的低内存标签页舍弃事件减少了 96%,服务器成效也非常有前景。

如需了解详情,请参阅 PATCH v14 00/14 多代 LRU 框架

我们目前使用的 Termina 5.15 没有 MGLRU 补丁。MGLRU 在上游不可用。终端内核开发者正在等待 MGLRU 被上游接受,以便向后移植 Termina 5.15

MGLRU API 可用于驱动免费网页报告逻辑。有必要研究使用 MGLRU API 来提高 Linux 内核中的免费页面报告性能。如果成功,则可以提议在上游合并。这将是对 Linux 内核中现有免费网页报告解决方案的优化。

在允许主机回收客户机内存方面,不依赖于 MGLRU。

常量提示框大小调整替代方法

最初推荐的方式是执行内存回收,因此叫做内存守护程序。

这是 ChromeOS 目前使用的方法。它有很多缺点

  • 需要选择轮询时间间隔。
  • Intel 报告称,即使是进行小型气球调整也会产生性能开销。请参阅持续调整提示框的大小会导致许多 TLB 崩溃
  • 为使该机制发挥作用,气泡必须始终膨胀到客户机内存的 90% 左右。
  • 访客应用可以快速分配,并在下一个轮询间隔之前被 OOM 守护程序终止

ChromeOS 方法

ChromeOS 目前正在开发下一代自适应 Virtio-气球。概括来讲,就是在客户机和主机中使用低内存终止守护进程来调整提示框大小,而不是终止应用。我们还计划使用 MGLRU 来指导提示框大小调整逻辑。

ChromeOS 正在解决另外一个更困难的问题:

  • ChromeOS 有多个访客和主机,它们会争用内存
  • ChromeOS 和所有客户机都可以连接 MGLRU 和低内存终止守护程序。
  • 选择合适的提示框大小是解决所有工作负载的难题。
    • 我们必须定义一组启发法来指导提示框膨胀/压缩逻辑
    • 重要的是获得来自设备群的数据,以便构建启发词语并分析其效果。
    • 更重要的是,如果您使用 LMKD 触发气球膨胀/收缩,则必须快速调整气球大小,否则 OOM 终止守护程序会在气球膨胀/拉紧时终止应用

Fuchsia 虚拟化没有庞大的设备群来收集统计信息。我们试图解决的问题要简单得多。Fuchsia 没有要关联的 OOM 杀手。

Fuchsia 主机允许同时运行多个客户机(Termina、Debian、Fuchsia)。目前,这并非主要用例,通常用户和测试运行单个访客。一旦我们开始使用更强大的硬件,此要求可能会改变。如果访客没有使用所有可用内存,则提议的解决方案将适用于多个超额订阅的访客。例如,空闲 Debian 访客和活跃的 Termina 访客。

如果我们必须支持多个尝试利用所有可用内存的访客,问题空间会大得多。确定哪个访客应用或哪个访客更重要应该成为一项产品政策。我们应该专注于为产品提供合适的工具,但在平台层面上,我们不希望对低内存的处理方式进行规范。

我们将采用更简单、更可预测的解决方案来解决当前问题,同时增加数据收集功能来分析 OOM,看看是否需要添加更复杂的启发法。

与 DAX 和 virtio-fs 共享主机和访客页面缓存

DAX 映射允许客户机直接从主机缓存访问文件内容,从而避免客户机和主机之间重复。使用 DAX 添加 virtio-fs 支持、启用页面缓存共享以及在内存压力时添加页面缓存舍弃,是 Virtio 提示框膨胀的替代解决方案,用于清除访客页面缓存。由于提示框膨胀,因此在控制页面缓存时,精细控制比通用页面缓存逐出更好。我们可以舍弃旧的页面缓存,同时保留新的页面缓存,以减轻内存压力,而不会过度影响主机/客户机的性能。

早期技术和参考资料