关注了就能看到更多这么棒的文章哦~

LRU-list manipulation with DAMON

By Jonathan Corbet
August 22, 2022
DeepL assisted translation
https://lwn.net/Articles/905370/

DAMON 子系统在 5.15 发布周期中进入了内核,它使用了一些启发式方法来确定哪些内存 page 正在被使用。从一开始,它的目的就是要利用这些信息来参与到内存管理中。6.0 内核中包含了这个方向的另一个步骤,那就是让 DAMON 有能力在内核的 least-recently-used(LRU)列表中主动对 page 进行重新排列。

内核的内存管理开发者最希望的是能够知道哪些内存 page 的内容会在后续很快需要被访问;然后内核可以确保把这些 page 驻留在 RAM 中。不幸的是,目前的硬件无法提供这种信息,所以内存管理代码必须进行一些猜测。通常情况下,一个相对最合理的猜测是,最近被使用过的 page 可能很快会被再次使用,而那些已经有一段时间没有被访问过的 page 可能不再需要了。

LRU lists

这种方法效果很好,但仍有一个问题:内核对每个 page 的使用情况的追踪无法非常细致。如果记下每一次访问的话,就会使系统变慢,所以必须要采取其他一些措施。LRU list 是内存管理子系统试图以有效方式来回答这个问题的一个方案。

详细一点来说的话,每个内存区(memory zone)以及每个 memory cgroup 都有两个 LRU list。如果更简化来看的话,系统中有两个 LRU list,称为 "active" 和 "inactive" list。正常使用的 page 会被放在 active list 的头部。随着时间的推移,它们会随着其他 page 加入头部而向下移,尽管有些情况下某个 page 也是可以回到头部的。到达了 active list 尾部的 page 相对来说更有可能在最近一段时间内是没有被使用的,但这种判断并不是完全精确的。

内核有些时候会把一组 page 从 active list 的尾部取出来,把它们放在 inactive list 的头部。当这种情况发生时,这些 page 就被 "deactivated "了,这意味着它们在 page list 中被标记为 "不存在"。如果某个进程试图访问这样的 page,就会产生一个 soft page fault;然后内核会观察到这个 page 仍然在使用,并将其移回 active list。而留在 inactive list 中的 page,则会不断移动到这个 list 的尾部,在内核需要回收内存用于其他用途时,会对它们进行回收。

因此,LRU list 是决定哪些 page 留在 RAM 中、哪些 page 被回收的机制中的一个关键部分。尽管它们的名字是这样起的,但这些 list 充其量只是对最近使用最少(或最多)的 page 的粗略估计而已。更好的描述可能是 "最近注意到被使用的最少的(least recently noticed to be used)"。如果有一个更好的机制来理解哪些 page 是真正被大量使用的,那么就有可能使用这些信息来改进当前的 LRU list。

Reordering the lists

DAMON("Data Access MONitor")就是希望成为这种机制。通过一些聪明的算法(在 https://lwn.net/Articles/812707/ 文章中有描述),DAMON 试图更清晰地了解内存使用的实际情况,同时又不至于耗费太多 CPU 资源。DAMON 被设计成在要在生产系统(production system)中也要足够高效,同时又足够精确,从而可以改善内存管理决策。

5.16 内核中增加了 DAMOS("DAMON operation schemes"),它增加了一个基于 rule 的机制,只要满足相应的标准,就可以触发相应的动作。例如,DAMOS 可以被配置为将一个在过去 N 秒内没有被访问的区域传递给一个 madvise(MADV_COLD) 类似功能的函数调用。还有其他多种选项,都在 Documentation/admin-guide/mm/damon/usage.rst 中进行了详细描述。

在 6.0 合并的这部分工作给 DAMOS 增加了两个新的操作:lru_prio 和 lru_deprio。第一个操作将导致指定的 page 被移到 active list 的头部,使它们成为内核试图 deactivate 或 reclaim 回收的最后一个 page;而第二个操作就会 deactivate 指定的 page,使它们被移到 inactive list 中。换句话说,有了这个改动之后,DAMOS 就深入到了内存管理子系统中,使用其(可能是)更加具有优势的信息来对 LRU list 进行排序,使其更接近于未来的真实情况。如果系统遇到突如其来的内存压力,必须要迅速开始回收内存,那么这些排序就可能会变的非常有用。

作者 SeongJae Park 称这种机制为 "proactive LRU-list sorting" 或 PLRUS。他在 patch 的说明邮件中声称,如果调整得好的话,这种机制可以得到一些不错的结果。"简而言之,PLRUS 减少了 10%的 memory PSI(some),major page fault 数量减少了 14%,以及在内存压力下得到了 3.74%的速度提升"。这里的术语 "PSI(some)"是指由内核产生的 pressure-stall 信息,它是衡量进程在等待内存时被 delay 程度有多严重。

不过,他说的 "如果调整得好的话" 这句提醒很重要;DAMOS 有一套复杂的参数来描述触发动作的阈值,并限制 DAMOS 本身使用多少 CPU 时间。调整这些参数可能会导致内存管理子系统核心代码的工作方式发生重大变动。DAMOS 为一个了解内存管理如何工作并能准确测量变动效果的全职管理人员提供了很大的灵活性。它也让彻底破坏系统的性能变得更加容易。

为了帮助那些没有时间或能力来为他们的工作场景提出最佳 DAMOS 设置的管理员,Park 还增加了一个新的内核 module,叫做 damon_lru_sort。它使用 DAMOS 在一组 "保守" (旨在安全地提高性能同时最大限度地减少开销)的参数下执行 proactive LRU-list 排序。这个 module 可以让 LRU list 排序功能变得更容易使用,但它仍然有一些主要的 tuning 开关;文档中对它们进行了详细描述。

这个机制旨在解决一个类似于 multi-generational LRU 这个工作所解决的问题,目前看来后者有望在 6.1 中合并。multi-generational LRU 也试图能更准确地确定哪些 page 正在被使用,从而可以做出更好的 page 替换决策。关于如何处理 page 在各个 generation 之间的移动,有一些尚未确定的问题;有人说可以允许加载 BPF 程序来控制这些决策,但是 DAMOS 可能也可以提供帮助。这两种机制之间的目前还没有整合,但可能是一个值得增加的好功能。

这种调整内存管理的能力的出现,显然是一个信号,说明人们总是希望有更好的性能。它也可能表明,创建一个对所有工作场景都能发挥最佳性能的内存管理子系统已经超出了我们目前的能力。内核开发者倾向于不增加新的配置开关,其理论是内核应该能够很好地完成自我配置。但是,在这个领域中还在大量地增加新的开关。有些问题对于内核来说似乎还是太难了,不得不寻求 user space 的帮助来解决。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

LWN: 使用DAMON调整LRU-list!相关推荐

  1. 动手实现一个 localcache - 设计篇

    前言 哈喽,大家好,我是asong.最近想动手写一个localcache练练手,工作这么久了,也看过很多同事实现的本地缓存,都各有所长,自己平时也在思考如何实现一个高性能的本地缓存,接下来我将基于自己 ...

  2. MySQL面试准备——64页pdf

    本笔记为以前整理的零碎的关于Mysql的知识点,有深入源码的也有浅层的八股.已经被我整理成了一个pdf. 实习岗位正好也是和数据库内核有关的,之后应该还会更新.做个整理,方便秋招的时候快速回顾吧. 链 ...

  3. mysql innodb缓存策略之Buffer Pool

    The InnoDB Buffer Pool Innodb 持有一个存储区域叫做buffer pool是为了在内存中缓存数据和索引,知道innodb bufferpool怎么工作,和利用它读取频繁访问 ...

  4. linux内存管理(十二)-直接页面回收

    在慢速回收路径中,首先是启动异步回收,异步回收失败后,就是下面准备讲解的内存直接回收了.直接页面回收过程分析,函数入口为__alloc_pages_direct_reclaim,函数位于mm/page ...

  5. Buffer Pool详解

    文章目录 一.简介 二.缓存页 三.Free链表 四.Flush链表 五.LRU链表 六.脏页刷新 七.多个Buffer pool 八.Chunk单位 一.简介 ​ mysql的数据都是存放在磁盘下的 ...

  6. Memcached哈希性能优化(八)——总结报告

    Memcached哈希性能优化报告 一. Memcached分析 这两个月一直在memcached优化和找工作之间忙着,一边复习一边优化改代码还真是个让人觉得难以忘记的夏天.做这个项目确实收获了很多, ...

  7. 《Mysql是怎样运行的》

    客户端查询mysql版本:select version(); 1 第1章 装作自己是个小白-重新认识MySQL 1.1 MySQL的客户端/服务器架构 每个进程都有一个唯一的编号,称为 进程ID ,英 ...

  8. 《MySQL是怎么运行的》阅读笔记

    mysql运行的整体架构简介 Mysql是由两部分构成,一部分是服务器程序,一部分是客户端程序. 服务器程序又包括两部分: 第一部分server层包括连接器.查询缓存.分析器.优化器.执行器等.涵盖 ...

  9. mysql原理(mysql是怎样运行的)

    一.MySQL的客户端/服务器架构: 1.mysql客户端服务端场景: a.启动MySQL服务器程序 b.启动MySQL客户端程序并连接到服务器程序. c.在客户端程序中输入一些命令语句作为请求发送到 ...

最新文章

  1. Python2的Json反序列化工具
  2. 如何定义视觉设计规范?
  3. scanner怎样回到文件开头_Radare2逆向分析dex/so/二进制等文件的使用方法
  4. Redis持久化总结
  5. 全面介绍Windows内存管理机制及C++内存分配实例(五):堆
  6. 前端基础牢记的一些操作-Github仓库管理
  7. 搜狗输入法语音转文字的体验点
  8. linux运行directory,我在linux里用命令出来is a directory是怎么回事
  9. 透过历史迷雾进行深入探究特斯拉线圈是如何工作的?
  10. 在微信群如何使用接龙功能
  11. 基因家族特征分析 - 染色体定位分析
  12. Excel服务器实现多用户协作
  13. 如何打造数据化决策管理
  14. jfs jfs2_故障诊断过程因JFS2 inode带有空扩展属性条目而挂起
  15. FFmpeg任意文件读取漏洞分析
  16. 01-初步认识数据库管理系统测试题
  17. Ubuntu16.04 打不开文件夹解决办法 | killall nautilus的原理 |nautilus命令快速打开文件
  18. 卷积神经网络(CNN)在语音识别中的应用
  19. Hive常用日期格式转换
  20. ansible基础-task控制

热门文章

  1. 不会js可以直接学vue吗
  2. [Professor麦]总结Spring的设计模式
  3. 测试用例设计方法_边界值分析法(游戏向)
  4. python支持字符类型吗_python核心数据类型 -- 字符串类型
  5. 第十四周项目二成绩姓名排名
  6. Java反射PropertyDescriptor的异常记录
  7. 大学物理实验——旋光仪的使用
  8. java 主函数解释
  9. [python自动化]简单实现接口自动化测试(基于python+unittest)
  10. 大模型们参加2023高考了,成绩单已出炉