RFC-0209:内存优先级配置文件

RFC-0209:内存优先级配置文件
状态已接受
领域
  • 内核
说明

使用配置文件为 VMAR 标记优先级。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2022-08-16
审核日期(年-月-日)2023-02-15

摘要

使用配置文件对象指示 以尽量减少页面故障和其他可能增加 通过允许将配置文件应用于 VMAR 来降低内存访问延迟。

设计初衷

Zircon 是一种过度使用系统,它采用不同的回收系统 来支持这些应用这些回收方法包括 逐出、页表回收、零页扫描等,并且可能出现不一致 因为这类任务可能会给内存带来不可接受的延迟时间 访问权限。将来可能采用的回收方法,如页面压缩, 也会出现问题

音频一直是个重复示例,内核会回收任何音频, 会导致音频线程中的后续页面错误,可能会导致音频线程 错过截止日期

到目前为止,解决方案一直是内核中的特殊情况解决方案, 来停用所有类型的回收,但只针对与音频相关的组件。不过, 这种方法非常脆弱,无法扩展到具有类似应用的 要求。

此 RFC 旨在提供一种适用于音频的通用机制, 现有的临时解决方法以及其他任何组件。

利益相关方

教员

jamesr@google.com

审核者

eieio@google.com、rashaeqbal@google.com、tombergan@google.com

已咨询

andresoportus@google.com

社交化

我们已在文档中与 Zircon 团队及 由内核进化工作组 (KEWG) 提供支持。

API 设计

为了向用户提供回收的控制,配置文件对象将 扩展到以下两方面:

  1. 附加标记ZX_PROFILE_INFO_FLAG_MEMORY_PRIORITY用于 系统将添加 zx_profile_creatememory_priority 字段。
  2. 可以通过 zx_object_set_profile 将配置文件应用于 VMAR。

最初仅支持 memory_priority 字段的两个值: ZX_PRIORITY_DEFAULTZX_PRIORITY_HIGH,为全部停用 并永久收回。剩余空间支持将来的其他级别 以便让您在最大限度地缩短延迟时间和防止 OOM 之间做出权衡。

当配置文件应用于 VMAR 时,假设该配置文件具有有效的 memory_priority,它会立即应用于该 VMAR 及其所有 子区域,覆盖之前应用的任何配置文件。

内核必须遵守 ZX_PRIORITY_HIGH 设置,并且内核必须停用已标记的 VMAR 中的任何动态回收。

ZX_PRIORITY_DEFAULT 设置没有特定的含义,也不 获得尊重。特别是,允许使用该内核,这主要是为了 实现,将 ZX_PRIORITY_HIGH 请求的适用范围扩大到 已标记为 ZX_PRIORITY_DEFAULT

虽然始终允许叠加应用,但如果地址空间从 如果没有任何 ZX_PRIORITY_HIGH VMAR,则内核应 返回到与未应用任何配置文件时相同的状态。

信息查询

zx_object_get_infoZX_INFO_KMEM_STATS_EXTENDED主题将是 扩展为报告一个附加字段:

    // The amount of memory in VMOs that would otherwise be tracked for
    // reclamation, but has had reclamation disabled.
    uint64_t vmo_reclaim_disabled_bytes;

组件使用情况

用户空间组件通常不会直接使用 zx_profile_create 等, 而是调用 ProfileProvider 服务。SetProfileByRole 放宽 ProfileProvider 的方法,以接受任意句柄, 而不只是线程

内核设计

本部分介绍如何将内核中的对象更改为 适应配置文件中的信息。我们的目标是 系统中可能需要知道内存优先级, 用户就可以高效获取决策如果可能,这种设计倾向于 在配置文件应用时运行,前提是配置文件 与其他操作相比,应用的频率较低。

归约为布尔值

回收涉及的内核对象包括:

  • VmAspace - 控制页面表映射和页面表回收 在这里。
  • VmAddressRegion - 目前没有参与回收,但 所有页表映射都通过此对象发生。
  • VmObject - 执行任何逐出或未来页面回收策略 VmObject

除了应用配置文件的对象 VmAddressRegion 之外, 每个对象都可以查询其任意子范围存在的 VMAR 以及应用的内存优先级

将多个具有不同优先级的 VMAR 应用于一个 VMO 区域 通过采用最高应用优先级解决

为避免在所有 VMAR 中反复长时间执行搜索,对象需要 快速了解是否有任何内存优先级适用于这些内存。为了简便起见, 最初提议的实施会将所有优先级范围升级为 整个对象。也就是说,如果 VmObject 的任何部分被 个人资料,则整个对象都会被视为具有该个人资料。

这两个实现简化使得高效的内存配置文件查询 只需要通过对象链接传播布尔值的并集即可。

繁殖

此回收停用布尔值的传播基于边缘转换 和计数。

为 VMAR 设置配置文件时,需要考虑以下三种结果:

  1. 此 VMAR 的回收保持不变。
  2. 回收从停用转换为启用。
  3. 回收从启用转换为停用。

在第一种情况下,不会发生直接传播,但所有次级区域仍然必须 并向其应用配置文件这种无条件遍历 因为某个子区域还应用了其他资料, 被覆盖

在这两个潜在引用对象的任一转换中,VmAspaceVmObject,需要更新。

VmAspaceVmObject 对象将使用一个布尔值,而不是一个布尔值 计数器,用于统计已停用回收功能的对象数量。 因此,确定是否对这些对象停用回收 也就是将计数和零进行比较

VmObject 可能还有其他需要传播的 VmObject 父级 标记。因为回收是由计数器控制的, 零,那么当计数器转换为零或从零转换时,传播会发生。

这种引用计数传播策略可确保配置文件更改 而且与仅跟踪 布尔值。

VmObject 转换

除了传播回收标志之外,VmObject 还需要执行 在过渡期间更新其页面的操作。

停用回收功能后,所有原本可以回收的页面都会 需要移动到单独的网页队列中。在此队列中 并提供浏览页数的方法。

同样,如果启用了回收功能 默认队列,使其再次成为回收候选对象。这是一个 在实施过程中,系统会详细考虑 放回其默认队列中。在无需访问硬件的平台上 标记将无法包含任何年龄信息,因此 能够创造无限可能。

实现

实现需要从内核执行一系列步骤 通过连续层的 API 来实施。

内核实现

针对内核对象更改提议的设计可以完全实现 增加了对在不更改任何代码的情况下设置内存优先级的支持 行为这将通过多个 CL 完成,并在内核中进行测试 单元测试。

内核 API 变更

ZX_INFO_KMEM_STATS_EXTENDED 查询需要一个具有较高特权的系统 并且只有很少的用法,全部都是在树中。因此,此查询 可以在单个 CL 中进行修改,而无需进行多阶段结构演变。

更新配置文件 API 和文档,并将配置文件系统调用关联到 之前实现的内核支持zx_profile_create 系统调用及其 关联的配置结构体 zx_profile_info_t 是特权系统 调用,因此同样可以在单个 CL 中进行修改。

ProfileProvider 变更

扩展 ProfileProvider 的实现,以支持一种指定方式 .profiles 中的内存优先级。

ProfileProvider FIDL API 更改为采用任意句柄,而不仅仅是 线程。由于这是对 API 的放宽,因此不会破坏 兼容性。

媒体迁移

媒体相关组件的相关配置文件将更改为包含 memory_priority(共 ZX_PRIORITY_HIGH),然后所有媒体组件都会 将这些配置文件应用于其根 VMAR,具体方式与其应用方式完全相同 添加到自己的会话串中。

确认配置文件运行正常后,现有硬编码内核 解决方法。

性能

建议的内核设计与 不同的是,当前的临时方法不能 未应用,对所有相关的 VMAR 和 VMO 而言是永久性的。因此, 从此方法到配置文件的操作都应是完全空操作, 包括 CPU 和内存使用情况。

安全注意事项

配置文件的使用以及设置内存优先级的能力取决于以下因素: 需要根作业句柄。因此,与您的网站相关的所有安全注意事项 等同于现有的拒绝服务攻击 ProfileProvider 的可能性。

测试

大部分测试可以集中在各自的单元测试 内核和配置文件提供程序实现,以及一些集成测试, 验证完整的使用路径。

文档

有关配置文件对象、相关系统调用和 FIDL 协议的文档 将进行更新。

替代方案

VMAR 上的媒体资源或同等资源

与其使用配置文件对象,不如直接设置一个属性或等效属性, 可用于指示其优先级。这样可以避免 扩展了调度器对象并简化了用户空间的使用,并且不会 需要 ProfileProvider 的参与。

使用这种方法,没有固有的方式来限制设置 优先级。尽管任何组件都可以分配任意内存和 执行拒绝服务攻击,这未必是理想之选, 回收应用很有可能是一种提高性能的方法, 导致了公地悲剧

我们可以设计某种形式的定制访问权限控制来解决这个问题, 但现在,利用配置文件的优势将不再显示。

通过污点进行推断

通过用户空间直接标记的一种替代方案是采用任何截止时间 线程需要访问截止时间内存,并将其访问的任何内存标记为高内存 优先级。这不需要对用户空间进行任何更改,但两类都需要超过 每个地址空间中至少有一个截止期限线程 映射 / VMO 在使用后被标记 被截止日期会话触发

过度标记是坏事,因为并非所有截止时间线程都有相同的内存延迟 而不是指向其所有地址空间延迟污点意味着 无法预先发生故障,因此截止期限线程在最糟糕的情况下 总是错过截止日期。

使用延迟标记方案时,也不清楚如何去掉商品。

将 memory_Priority 应用于线程

memory_priority 字段无需将配置文件应用于 VMAR, 在配置文件应用于线程时进行解释, 应用于其根 VMAR

尽管这简化了 ProfileProvider 协议以及 系统调用接口,它会让用户和内核无法选择更多 未来效率最高。高效的组件可以进行整理, 将延迟时间敏感数据存储在其地址空间的一个子区域中, 数据,只需将配置文件应用于关键区域即可。这个 使非关键数据仍是考虑回收的考虑因素,有利于 内存用量。

单优先级字段

线程优先级的同一 priority 字段可重复使用,而不是 附加的 memory_priority 字段。这就产生了一个理论 不需要使用更简单的配置结构,但现在需要 如果设置了不同的内存和调度器优先级,则要创建的配置文件对象 。

正在展开 ALWAYS_NEED 条提示

现有的 API 使用 ALWAYS_NEED 和 针对 VMO 或 VMAR 的 DONT_NEED 提示。目前,这些标记仅具有 分页器支持 VMO,但也可扩展为对匿名 VMO 有意义。

如果只是扩展语义以涵盖匿名 VMO,就会产生一些缺口:

  • ALWAYS_NEED 并不保证一定不回收,因为它只是一种提示。
  • 由于系统仍会跟踪存在时间,因此网页仍可能需要访问故障。
  • 不会停用页面表回收。
  • 只能应用于现有映射。

以上每一个限制都可以使用内部实现方法来解决。 与主要提案中描述的内容类似,不过,API 本身 两个基本问题。

主提案在重新启用回收时有明确的方法 方法是将配置文件应用于所有 VMAR(或仅应用于根 VMAR)。含微调 无法移除 ALWAYS_NEED,因为 DONT_NEED 强于撤消 ALWAYS_NEED

提示 API 成为提示而非 promise 的一个动机是, 缺少访问权限控制,无法在任何 VMAR 或 VMO 上使用。作业政策或 可以用来控制提示的用途, 都需要加以设计