背景

回收干净文件 large folio 时,内核要检查它的 PTE 上是否还有 young 标志(最近是否被访问),以此判断该 folio 是否还值得保留。folio_referenced_one() 逐 PTE 顺序做这件事,对 large folio 来说很慢:它已成为干净文件 large folio 回收的显著性能热点。

┌──────────────────────────────────────┐
│ 回收干净文件大页时,逐个表项查访问标 │
│ 志                                   │
└──────────────────┬───────────────────┘
                   ▼
┌──────────────────────────────────────┐
│ 连续表项优化只覆盖一小段,大页可能超 │  逐表项处理在回收热路径上低效
│ 出                                   │
└──────────────────┬───────────────────┘
                   ▼
┌──────────────────────────────────────┐
│         取消映射也逐个表项做         │  文件大页回收是显著热点
└──────────────────────────────────────┘

Arm64 支持 contiguous PTEs,已有对连续范围内清 young 标志的优化。但 large folio 可能超出一个连续范围(CONT_PTE_SIZE),这点优化覆盖不全。同样,对文件 large folio 的取消映射(unmap)也是逐 PTE 做的,同样是回收路径上的开销。

问题

  • 回收文件大页时逐个表项查访问标志
  • 连续表项优化只覆盖一小段,大页可能超出
  • 取消映射也逐个表项做
  • 文件大页回收的逐表项处理是显著热点

方案

核心是给 large folio 的 rmap 操作引入批量 PTE 处理:一条调用覆盖整个 large folio 的 PTE 批,包括检查 young 标志、清 young 标志 + flush TLB、以及取消映射。

旧:逐表项查清访问标志、逐个取消映射
┌────────────────────┐
│ 检查访问标志逐表项 │
└─────────┬──────────┘
          ▼
┌────────────────────┐
│  取消映射也逐个做  │
└────────────────────┘

新:批量检查标志、清标志、取消映射
┌──────────────────────────────┐
│ 新接口一次检查整批表项并冲刷 │
└──────────────┬───────────────┘
               ▼
┌──────────────────────────────┐
│   架构落地更高效的批量实现   │  文件大页批量取消映射也已支持
└──────────────────────────────┘

系列分 3 层把这个批量能力建起来。

第 1 层是通用 API。引入 clear_flush_young_ptes(),单次调用覆盖整个 large folio 的 PTE 批,做检查 young、清 young 加 flush TLB;旧的 ptep_clear_flush_young_notify() 顺势 rename 为 clear_flush_young_ptes_notify(),体现批量语义。

第 2 层是架构落地。批量 API 只有通用慢路径不够,arm64 利用 contiguous PTE 硬件能力实现专用的批量清 young 与 clear_flush_young_ptes()(先把地址与 ptep 对齐抽成 helper 复用),让批量操作真正高效。large folio 可能超出某个连续范围,这套实现把多个连续段串起来覆盖整个 folio。

第 3 层是文件 large folio 的取消映射。回收路径上 unmap 也是逐 PTE 做的,同样改成批量;uffd 路径因语义不同仍 fallback 逐页。

收益

作者在 Arm64 32 核服务器和 X86 机器上测试(mmap 分配 10G 干净文件 folio 到 memcg,经 memory.reclaim 回收 8G):

平台 W/o patch W/ patch 改善
Arm64 32 核(reclaim 8G 耗时) 1.018s 0.249s ~75%
X86(reclaim 8G) 50%+

回收 8G 干净文件 large folios 的耗时从 1.018 秒降到 0.249 秒(Arm64 75%),X86 也有 50%+ 改善。批量 PTE 处理把逐 PTE 的检查、清标志、flush、取消映射都压成整批操作,文件 large folio 回收因此大幅提速。