多代 LRU

多代 LRU 是一种替代的 LRU 实现,它优化了页面回收,并在内存压力下提高了性能。页面回收决定了内核的缓存策略和超额分配内存的能力。它直接影响 kswapd 的 CPU 使用率和 RAM 效率。

快速入门

使用以下配置构建内核。

  • CONFIG_LRU_GEN=y

  • CONFIG_LRU_GEN_ENABLED=y

一切就绪!

运行时选项

/sys/kernel/mm/lru_gen/ 包含以下小节中描述的稳定 ABI。

终止开关

enabled 接受不同的值来启用或禁用以下组件。它的默认值取决于 CONFIG_LRU_GEN_ENABLED。除非其中一些组件有不可预见的副作用,否则应启用所有组件。当硬件不支持某个组件时,写入 enabled 无效,即使主开关关闭,也会接受有效值。

组件

0x0001

多代 LRU 的主开关。

0x0002

当 MMU 设置时(例如,在 x86 上),以大批量清除叶页表条目中的访问位。这种行为理论上会加剧锁争用 (mmap_lock)。如果禁用它,对于连续映射热页的工作负载,多代 LRU 的性能会略有下降,否则这些热页的访问位可以通过更少更大的批量清除。

0x0004

当 MMU 设置时(例如,在 x86 上),也清除非叶页表条目中的访问位。这种行为未在 Intel 和 AMD 以外的 x86 变体上验证。如果禁用它,多代 LRU 的性能会略微下降。

[yYnN]

应用于上述所有组件。

例如,

echo y >/sys/kernel/mm/lru_gen/enabled
cat /sys/kernel/mm/lru_gen/enabled
0x0007
echo 5 >/sys/kernel/mm/lru_gen/enabled
cat /sys/kernel/mm/lru_gen/enabled
0x0005

防止抖动

个人计算机对抖动更敏感,因为它会导致抖动(渲染 UI 时出现延迟)并对用户体验产生负面影响。多代 LRU 为大多数没有 oomd 的笔记本电脑和台式机用户提供抖动预防功能。

用户可以写入 Nmin_ttl_ms,以防止 N 毫秒的工作集被逐出。如果无法将此工作集保留在内存中,则会触发 OOM 杀手。换句话说,此选项充当可调节的减压阀,当打开时,它会终止希望没有被使用的应用程序。

基于平均人类可检测到的延迟(约 100 毫秒),N=1000 通常可以消除由于抖动引起的无法容忍的抖动。像 N=3000 这样更大的值会使抖动不太明显,但存在过早 OOM 杀死的风险。

默认值 0 表示禁用。

实验性功能

/sys/kernel/debug/lru_gen 接受以下小节中描述的命令。支持多条命令行,也支持使用分隔符 ,; 进行连接。

/sys/kernel/debug/lru_gen_full 提供用于调试的附加统计信息。CONFIG_LRU_GEN_STATS=y 将此文件中已逐出代系的统计历史信息保存。

工作集估计

工作集估计衡量应用程序在给定时间间隔内需要多少内存,它通常对应用程序的性能影响很小。例如,数据中心希望优化作业调度(装箱),以提高内存利用率。当一个新作业进入时,作业调度器需要找出它管理的每个服务器是否可以在选择候选服务器之前为这个新作业分配一定量的内存。为此,作业调度器需要估计现有作业的工作集。

读取时,lru_gen 返回每个 memcg 和节点在不同时间间隔内访问的页面数的直方图。MAX_NR_GENS 决定每个直方图的 bin 数量。直方图是非累积的。

memcg  memcg_id  memcg_path
   node  node_id
       min_gen_nr  age_in_ms  nr_anon_pages  nr_file_pages
       ...
       max_gen_nr  age_in_ms  nr_anon_pages  nr_file_pages

每个 bin 都包含在 age_in_ms 内访问的页面的估计数量。例如,min_gen_nr 包含最冷的页面,而 max_gen_nr 包含最热的页面,因为前者的 age_in_ms 最大,后者的 age_in_ms 最小。

用户可以将以下命令写入 lru_gen 以创建新代 max_gen_nr+1

+ memcg_id node_id max_gen_nr [can_swap [force_scan]]

can_swap 默认为交换设置,如果设置为 1,则在交换关闭时强制扫描匿名页面,反之亦然。force_scan 默认为 1,如果设置为 0,则使用启发式方法来减少开销,这可能会降低覆盖率。

一个典型的用例是,作业调度器在某个时间间隔运行此命令以创建新代,并根据该时间间隔定义的冷页大小对其管理的服务器进行排名。

主动回收

主动回收会在没有内存压力时触发页面回收。它通常只针对冷页面。例如,当一个新作业进入时,作业调度器希望在它选择的服务器上主动回收冷页面,以提高成功启动此新作业的机会。

用户可以将以下命令写入 lru_gen 以逐出小于或等于 min_gen_nr 的代。

- memcg_id node_id min_gen_nr [swappiness [nr_to_reclaim]]

min_gen_nr 应该小于 max_gen_nr-1,因为 max_gen_nrmax_gen_nr-1 没有完全老化(等同于活动列表),因此不能被驱逐。swappiness 会覆盖 /proc/sys/vm/swappiness 中的默认值。nr_to_reclaim 限制了要驱逐的页面数量。

一个典型的用例是,作业调度器在尝试在服务器上部署新作业之前运行此命令。如果由于高估而未能实现足够的冷页面,它会根据从工作集估计步骤获得的排名结果,在下一个服务器上重试。这种不那么强制的方法限制了对现有作业的影响。