diff --git a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md index b3a384f..978c32d 100644 --- a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md +++ b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md @@ -991,7 +991,7 @@ https://lore.kernel.org/patchwork/cover/668967 | 2016/04/15 | "Uladzislau Rezki (Sony)" | [mm/vmalloc: Keep a separate lazy-free list](https://lore.kernel.org/patchwork/cover/669083) | 将惰性释放的 vmap_area 添加到一个单独的无锁空闲 vmap_purge_list, 这样我们就不必在每次清除时遍历整个列表. | v2 ☑ 4.7-rc1 | [PatchWork v1](https://lore.kernel.org/patchwork/cover/667471)
*-*-*-*-*-*-*-*
[PatchWork v2](https://lore.kernel.org/patchwork/cover/669083)
*-*-*-*-*-*-*-*
[commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=80c4bd7a5e4368b680e0aeb57050a1b06eb573d8) | | 2019/04/06 | "Uladzislau Rezki (Sony)" | [improve vmap allocation](https://lore.kernel.org/patchwork/cover/1059021) | [improve vmalloc allocation](https://patchwork.kernel.org/project/linux-mm/cover/20181019173538.590-1-urezki@gmail.com) 的 RESEND 和再版. 优化 alloc_vmap_area(), 优化查找复杂度从 O(N) 下降为 O(logN). 目前新的 VA 区域的分配是在繁忙列表(vmap_area_list/root)迭代中完成的, 直到在两个繁忙区域之间找到一个合适的空洞. 因此, 每次新的分配都会导致列表增长. 查找空洞的代价为 O(N). 而通过跟踪空闲的 vmap_area 区域, 并在空闲列表搜索空洞来完成分配, 可以将分配的开销降到 O(logN). 在初始化阶段 vmalloc_init() 中, vmalloc 内存布局将[对空闲区域进行跟踪和组织](https://elixir.bootlin.com/linux/v5.2/source/mm/vmalloc.c#L1880), 并用链表 free_vmap_area_list 和 红黑书 free_vmap_area_root 组织. 为了优化查找效率, vmap_area 中 subtree_max_size 存储了其节点为根的红黑树中最大的空洞大小. | v3 ☑ [5.2-rc7](https://kernelnewbies.org/Linux_5.2#Memory_management) | [PatchWork RFC](https://lore.kernel.org/patchwork/cover/1002038)
*-*-*-*-*-*-*-*
[PatchWork v4](https://patchwork.kernel.org/project/linux-mm/patch/20190406183508.25273-2-urezki@gmail.com)
*-*-*-*-*-*-*-*
[PatchWork v3](https://lore.kernel.org/patchwork/cover/1057418) | | 2019/07/06 | Pengfei Li | [mm/vmalloc.c: improve readability and rewrite vmap_area](https://lore.kernel.org/patchwork/cover/1101062) | 为了减少结构体 vmap_area 的大小.
1. "忙碌"树可能相当大, 即使区域被释放或未映射, 它仍然停留在那里, 直到"清除"逻辑删除它. 优化和减少"忙碌"树的大小, 在用户触发空闲路径时立即删除一个节点. 这样做是可能的, 因为分配是使用另一个扩展树完成的;这样忙碌的树将只包含分配的区域, 不会干扰惰性空闲的节点, 引入新的函数 show_purge_info(), 转储通过"/proc/vmallocinfo" 来显示 "unpurged" 区域.
2. 由于结构体 vmap_area 的成员不是同时使用的, 所以可以通过将几个不同时使用的成员放入联合中来减少其大小. | v6 ☑ 5.4-rc1 | [PatchWork v1,0/5](https://lore.kernel.org/patchwork/cover/1095787)
*-*-*-*-*-*-*-*
[PatchWork v2,0/5](https://lore.kernel.org/patchwork/cover/1096583)
*-*-*-*-*-*-*-*
[PatchWork v6,0/2](https://patchwork.kernel.org/project/linux-mm/cover/20190716152656.12255-1-lpf.vector@gmail.com) | -| 2020/11/16 | "Uladzislau Rezki (Sony)" | [mm/vmalloc: rework the drain logic](https://lore.kernel.org/patchwork/cover/1339347) | 当前的"惰性释放”模式至少存在两个问题:
1. 由于只有 vmap_purge_list 链表组织, 因此 vmap 区域的未排序的, 因此为了识别要耗尽的区域的 [min:max] 范围, 它需要扫描整个 vmap_purge_list 链表. 可能会耗费较多时间.
2. 作为下一步是关于合并所有片段与自由空间.这也是一种耗时的操作, 因为它必须遍历包含突出惰性区域的整个列表. 这造成了极高的延迟. | v1 ☑ 5.11-rc1 | [PatchWork](https://patchwork.kernel.org/project/linux-mm/patch/20201116220033.1837-2-urezki@gmail.com) | +| 2020/11/16 | "Uladzislau Rezki (Sony)" | [mm/vmalloc: rework the drain logic](https://lore.kernel.org/patchwork/cover/1339347) | 当前的"惰性释放"模式至少存在两个问题:
1. 由于只有 vmap_purge_list 链表组织, 因此 vmap 区域的未排序的, 因此为了识别要耗尽的区域的 [min:max] 范围, 它需要扫描整个 vmap_purge_list 链表. 可能会耗费较多时间.
2. 作为下一步是关于合并所有片段与自由空间.这也是一种耗时的操作, 因为它必须遍历包含突出惰性区域的整个列表. 这造成了极高的延迟. | v1 ☑ 5.11-rc1 | [PatchWork](https://patchwork.kernel.org/project/linux-mm/patch/20201116220033.1837-2-urezki@gmail.com) | | 2019/10/22 | Uladzislau Rezki (Sony) | [mm/vmalloc: rework vmap_area_lock](https://lore.kernel.org/patchwork/cover/1143029) | 随着 5.2 版本 [improve vmap allocation](https://lore.kernel.org/patchwork/cover/1059021) 的合入, 全局的 vmap_area_lock 可以被拆分成两个锁: 一个用于分配部分(vmap_area_lock), 另一个用于回收(free_vmap_area_lock), 因为有两个不同的实体: "空闲数据结构"和"繁忙数据结构". 这和那后的减少锁争用, 允许在不同的 CPU 上并行执行"空闲"和"忙碌"树的操作. 但是需要注意的是, 分配/释放操作仍然存在依赖. 如果在不同的 CPU 上同时运行, 分配/释放操作仍然会相互干扰. | v1 ☑ 5.5-rc1 | [PatchWork v2,0/8](https://patchwork.kernel.org/project/linux-mm/patch/20191022155800.20468-1-urezki@gmail.com)
*-*-*-*-*-*-*-*
[commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e36176be1c3920a487681e37158849b9f50189c4) | @@ -1220,7 +1220,7 @@ gpu 和高吞吐量设备在 TLB 丢失和随后的页表遍行情况下, 与 CP 为什么要引入迁移类型. 我们都知道伙伴系统是针对于解决外碎片的问题而提出的, 那么为什么还要引入这样一个概念来避免碎片呢? -在去碎片化时, 需要移动或回收页面, 以腾出连续的物理页面, 但可能一颗“老鼠屎就坏了整锅粥”——由于某个页面无法移动或回收, 导致整个区域无法组成一个足够大的连续页面块. 这种页面通常是内核使用的页面, 因为内核使用的页面的地址是直接映射(即物理地址加个偏移就映射到内核空间中), 这种做法不用经过页表翻译, 提高了效率, 却也在此时成了拦路虎. +在去碎片化时, 需要移动或回收页面, 以腾出连续的物理页面, 但可能一颗"老鼠屎就坏了整锅粥"——由于某个页面无法移动或回收, 导致整个区域无法组成一个足够大的连续页面块. 这种页面通常是内核使用的页面, 因为内核使用的页面的地址是直接映射(即物理地址加个偏移就映射到内核空间中), 这种做法不用经过页表翻译, 提高了效率, 却也在此时成了拦路虎. 我们注意到, 碎片一般是指散布在内存中的小块内存, 由于它们已经被分配并且插入在大块内存中, 而导致无法分配大块的连续内存. 而伙伴系统把内存分配出去后, 要再回收回来并且重新组成大块内存, 这样一个过程必须建立两个伙伴块必须都是空闲的这样一个基础之上, 如果其中有一个伙伴不是空闲的, 甚至是其中的一个页不是空闲的, 都会导致无法分配一块连续的大块内存. 我们引用一个例子来看这个问题: @@ -1270,6 +1270,7 @@ Mel Gorman 观察到, 所有使用的内存页有三种情形: 它后来替代了成块回收, 使得后者在 3.5 中被移除. +[memory compaction 原理、实现与分析](https://blog.csdn.net/21cnbao/article/details/118687445) | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| @@ -1280,7 +1281,7 @@ Mel Gorman 观察到, 所有使用的内存页有三种情形: | 2012/09/21 | Mel Gorman | [Reduce compaction scanning and lock contention](https://lore.kernel.org/patchwork/cover/327667) | 进一步优化内存规整的扫描耗时和锁开销. | v1 ☑ 3.7-rc1 | [PatchWork v1](https://lore.kernel.org/patchwork/cover/327667) | | 2013/12/05 | Mel Gorman | [Removal of lumpy reclaim V2](https://lore.kernel.org/patchwork/cover/296609) | 添加了 start 和 end 两个 tracepoint, 用于内存规整的开始和结束. 通过这两个 tracepoint 可以计算工作负载在规整过程中花费了多少时间, 并可能调试与用于扫描的缓存 pfns 相关的问题. 结合直接回收和 slab 跟踪点, 应该可以估计工作负载的大部分与分配相关的开销. | v2 ☑ 3.14-rc1 | [PatchWork v2](https://lore.kernel.org/patchwork/cover/296609) | | 2014/02/14 | Joonsoo Kim | [compaction related commits](https://lore.kernel.org/patchwork/cover/441817) | 内存规整相关清理和优化. 降低了内存规整 9% 的运行时间. | v2 ☑ 3.15-rc1 | [PatchWork v2 0/5](https://lore.kernel.org/patchwork/cover/441817) | -| 2015/07/02 | Mel Gorman | [Outsourcing compaction for THP allocations to kcompactd](https://lore.kernel.org/patchwork/cover/575290) | 实现 per node 的 kcompactd 内核线程来定期触发内存规整. | RFC v2 ☑ 4.6-rc1 | [PatchWork RFC v2](https://lore.kernel.org/patchwork/cover/575290) | +| 2015/07/02 | Mel Gorman | [Outsourcing compaction for THP allocations to kcompactd](https://lore.kernel.org/patchwork/cover/650051) | 实现 per node 的 kcompactd 内核线程来定期触发内存规整. | RFC v2 ☑ 4.6-rc1 | [PatchWork RFC v2](https://lore.kernel.org/patchwork/cover/650051) | | 2016/08/10 | Mel Gorman | [make direct compaction more deterministic](https://lore.kernel.org/patchwork/cover/692460) | 更有效地直接规整(压缩迁移). 在内存分配的慢速路径 `__alloc_pages_slowpath` 中的之前一直会先尝试直接回收和规整, 直到分配成功或返回失败.
1. 当回收先于压缩时更有可能成功, 因为压缩需要满足某些苛刻的条件和水线要求, 并且在有更多的空闲页面时会增加压缩成功的概率.
2. 另一方面, 从轻异步压缩(如果水线允许的话)开始也可能更有效, 特别是对于较小 order 的申请. 因此[这个补丁])(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a8161d1ed6098506303c65b3701dedba876df42a)将慢速路径下的尝试流程修正为将先进行 MIGRATE_ASYNC 异步迁移(规整), 再尝试内存直接回收, 接着进行 MIGRATE_SYNC_LIGHT 轻度同步迁移(规整). 并引入了[直接规整的优先级](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a5508cd83f10f663e05d212cb81f600a3af46e40). | RFC v2 ☑ 4.8-rc1 & 4.9-rc1 | [PatchWork v3](https://lore.kernel.org/patchwork/cover/692460)
*-*-*-*-*-*-*-*
[PatchWork series 1 v5](https://lore.kernel.org/patchwork/cover/700017)
*-*-*-*-*-*-*-*
[PatchWork series 2 v6](https://lore.kernel.org/patchwork/cover/705827) | | 2017/03/07 | Vlastimil Babka | [try to reduce fragmenting fallbacks](https://lore.kernel.org/patchwork/cover/766804) | 修复 [Regression in mobility grouping?](https://lkml.org/lkml/2016/9/28/94) 上报的碎片化问题, 通过修改 fallback 机制和 compaction 机制来减少永久随便化的可能性. 其中 fallback 修改时, 仅尝试从不同 migratetype 的 pageblock 中窃取的页面中挑选最小(但足够)的页面. | v3 ☑ [4.12-rc1](https://kernelnewbies.org/Linux_4.12#Memory_management) | [PatchWork v6](https://lore.kernel.org/patchwork/cover/766804), [KernelNewbies](https://kernelnewbies.org/Linux_4.12#Memory_management), [关键 commit 3bc48f96cf11 ("mm, page_alloc: split least stolen page in fallback")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3bc48f96cf11ce8699e419d5e47ae0d456403274) | | 2019/01/18 |Mel Gorman | [Increase success rates and reduce latency of compaction v3](https://lore.kernel.org/patchwork/cover/1033508) | 提高内存规整成功率并减少规整的延迟, 将用于迁移的扫描页面数减少 65%, 将用于迁移目标的可用页面数减少97%, 同时显著提高透明的hugepage分配成功率.
这组补丁通过使用自由列表来缩短扫描, 更好地控制跳过信息, 以及是否多个扫描可以瞄准同一块并在被并行请求窃取之前捕获页块, 从而降低了扫描率和压缩成功率.
使用了 THPscale 来衡量和测试这组补丁的影响. 基准测试创建一个大文件, 映射它, 使它出错, 在映射中打洞, 使虚拟地址空间碎片化, 然后试图分配THP. 对于不同数量的线程, 它将重新执行. 从碎片的角度来看, 工作负载是相对良性的, 但它会压缩压力. 为迁移而扫描的页面数量减少了65%, 空闲扫描器减少了97.5%. 更少的工作换来更低的延迟和更高的成功率.
这组补丁还使用了严重碎片内存的工作负载进行了评估, 但也有很大的好处. | v3 ☑ [5.1-rc1](https://kernelnewbies.org/Linux_5.1#Memory_management) | [PatchWork 00/22](https://lore.kernel.org/patchwork/cover/1033508) | @@ -1450,7 +1451,7 @@ Mel Gorman 观察到, 所有使用的内存页有三种情形: | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| -| 2006/02/01 | Christoph Lameter | [Reclaim slab during zone reclaim](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2a16e3f4b0c408b9e50297d2ec27e295d490267) | 引入 RECLAIM_SLAB 全局回收 SLAB 页面.
如果大量的 zone 内存被空的 slab 占用, 那么 zone_reclaim 将变得无效. 这个补丁的问题是, slab 回收不能包含到一个区域. 因此, 板坯回收可能会影响整个系统, 而且速度极慢. 这也意味着我们无法确定在这个区域中释放了多少页. 因此, 我们需要离开节点进行至少一次分配. 缺省情况下,该功能是禁用的. | v1 ☑ 2.6.16-rc2 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2a16e3f4b0c408b9e50297d2ec27e295d490267) | +| 2006/02/01 | Christoph Lameter | [Reclaim slab during zone reclaim](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2a16e3f4b0c408b9e50297d2ec27e295d490267) | 引入 RECLAIM_SLAB 全局回收 SLAB 页面.
如果大量的 zone 内存被空的 slab 占用, 那么 zone_reclaim 将变得无效. 这个补丁的问题是, slab 回收不能包含到一个区域. 因此, 板坯回收可能会影响整个系统, 而且速度极慢. 这也意味着我们无法确定在这个区域中释放了多少页. 因此, 我们需要离开节点进行至少一次分配. 缺省情况下, 该功能是禁用的. | v1 ☑ 2.6.16-rc2 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2a16e3f4b0c408b9e50297d2ec27e295d490267) | | 2006/02/01 | Christoph Lameter | [zone_reclaim: dynamic slab reclaim](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0ff38490c836dc379ff7ec45b10a15a662f4e5f6) | 如果释放未映射的文件备份页面不足以释放, 只能通过手动配置 RECLAIM_SLAB 来启用 slab 回收, 释放更多内存. 但是这样并不好控制. 因此这个补丁将 slab 回收修改为在 zone reclaim 过程中自动进行. 因此删除了 zone_reclaim_mode 中 RECLAIM_SLAB 选项
1. 如果 page cache 数量不足, 则收缩每个节点的页面缓存, 页面大于区域中页面的min_unmapped_ratio百分比.
2. 如果可回收 slab 页面的节点数量不足, 则收缩 slab 缓存. 引入了一个 min_slab_ratio 参数控制 slab 的比例. | v1 ☑ 2.6.19-rc1 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0ff38490c836dc379ff7ec45b10a15a662f4e5f6) | * RECLAIM_UNMAP @@ -2021,7 +2022,7 @@ Facebook 指出他们也面临过同样的问题, 所有的 workload 都需要 | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| -| 2021/08/09 | SeongJae Park | [mm: introduce process_mrelease system call](https://lore.kernel.org/patchwork/patch/1474134) | 引入 process_mrelease() 加速进程的清理, 以更快地释放被杀死的进程的内存.
我们经常希望能杀死不必要的进程, 为更重要的进程释放内存. 例如 Facebook 的 OOM killer 守护程序 oomd 和 Android的低内存killer守护程序lmkd. 对于这样的系统组件, 能够快速有效地释放内存非常. 但是不幸的是, 当一个进程接收到 SIGKILL 信号的时候并不一定能及时释放自己的内存, 这可能会受到很多因素的影响, 譬如进程的状态(它可能是处于 uninterruptible sleep 态)、正在运行进程的的 core 的 OPP 级别等. 而通过调用这个新的 process_mrelease() 系统调用, 它会在调用者的上下文中释放被杀死的进程的内存. 这种方式下, 内存的释放更可控, 因为它直接在当前 CPU 上运行, 只取决于调用者任务的优先级大小. 释放内存的工作量也将由调用方承担. | v9 ☑ 5.15-rc1 | [PatchWork v9,1/2](https://lore.kernel.org/patchwork/cover/1474134) | +| 2021/08/09 | SeongJae Park | [mm: introduce process_mrelease system call](https://lore.kernel.org/patchwork/patch/1474134) | 引入 process_mrelease() 加速进程的清理, 以更快地释放被杀死的进程的内存.
我们经常希望能杀死不必要的进程, 为更重要的进程释放内存. 例如 Facebook 的 OOM killer 守护程序 oomd 和 Android的低内存killer守护程序lmkd. 对于这样的系统组件, 能够快速有效地释放内存非常. 但是不幸的是, 当一个进程接收到 SIGKILL 信号的时候并不一定能及时释放自己的内存, 这可能会受到很多因素的影响, 譬如进程的状态(它可能是处于 uninterruptible sleep 态)、正在运行进程的的 core 的 OPP 级别等. 而通过调用这个新的 process_mrelease() 系统调用, 它会在调用者的上下文中释放被杀死的进程的内存. 这种方式下, 内存的释放更可控, 因为它直接在当前 CPU 上运行, 只取决于调用者任务的优先级大小. 释放内存的工作量也将由调用方承担. | v9 ☑ [5.15-rc1](https://kernelnewbies.org/LinuxChanges#Linux_5.15.Introduce_process_mrelease.282.29_system_call) | [PatchWork v9,1/2](https://lore.kernel.org/patchwork/cover/1474134) | @@ -2158,7 +2159,7 @@ Linux内核的一大特色就是支持最多的文件系统, 并拥有一个虚 这种固定的128 KB预读方案显然不是最优的. 它没有考虑系统内存使用状况和进程读取情况. 当内存紧张时, 过度的预读其实是浪费, 预读的页面可能还没被访问就被踢出去了. 还有, 进程如果访问得凶猛的话, 且内存也足够宽裕的话, 128KB又显得太小家子气了. -后续通过 Steven Pratt、Ram Pai 等人的大量工作, readahead算法进一步完善. 其中最重要的一点是实现了对随机读的完好支持. 随机读在数据库应用中处于非常突出的地位. 在此之前, 预读算法以离散的读页面位置作为输入, 一个多页面的随机读会触发“顺序预读”. 这导致了预读I/O数的增加和命中率的下降. 改进后的算法通过监控所有完整的 read( )调用, 同时得到读请求的页面偏移量和数量, 因而能够更好的区分顺序读和随机读. +后续通过 Steven Pratt、Ram Pai 等人的大量工作, readahead算法进一步完善. 其中最重要的一点是实现了对随机读的完好支持. 随机读在数据库应用中处于非常突出的地位. 在此之前, 预读算法以离散的读页面位置作为输入, 一个多页面的随机读会触发"顺序预读". 这导致了预读I/O数的增加和命中率的下降. 改进后的算法通过监控所有完整的 read( )调用, 同时得到读请求的页面偏移量和数量, 因而能够更好的区分顺序读和随机读. 2.6.23的内核引入了在这个领域耕耘许久的吴峰光的一个[按需预读的算法]((https://lwn.net/Articles/235164). 所谓的按需预读, 就是内核在读取某页不在内存时, 同步把页从外设读入内存, 并且, 如果发现是顺序读取的话, 还会把后续若干页一起读进来, 这些预读的页叫预读窗口; 当内核读到预读窗口里的某一页时, 如果发现还是顺序读取的模式, 会再次启动预读, 异步地读入下一个预读窗口. @@ -2363,7 +2364,7 @@ LWN 上 Mel 写的关于 Huge Page 的连载. | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| | 2020/12/22 | Liang Li | [add support for free hugepage reporting](https://lore.kernel.org/patchwork/cover/1355899) | Free page reporting 只支持伙伴系统中的页面, 它不能报告为 hugetlbfs 预留的页面. 这个补丁在 hugetlb 的空闲列表中增加了对报告巨大页的支持, 它可以被 virtio_balloon 驱动程序用于内存过载和预归零空闲页, 以加速内存填充和页面错误处理. | RFC ☐ | [PatchWork RFC,0/3](https://patchwork.kernel.org/project/linux-mm/cover/20201222074538.GA30029@open-light-1.localdomain) | -| 2021/10/07 | Mike Kravetz | [hugetlb: add demote/split page functionality](https://lore.kernel.org/patchwork/cover/1465517) | 实现了 hugetlb 降低策略. 提供了一种“就地”将 hugetlb 页面分割为较小的页面的方法. | v4 ☐ | [2021/07/21 PatchWork 0/8](https://patchwork.kernel.org/project/linux-mm/cover/20210721230511.201823-1-mike.kravetz@oracle.com)
*-*-*-*-*-*-*-*
[2021/08/16 PatchWork RESEND,0/8](https://patchwork.kernel.org/project/linux-mm/cover/20210816224953.157796-1-mike.kravetz@oracle.com)
*-*-*-*-*-*-*-*
[2021/09/23 PatchWork v2,0/4](https://patchwork.kernel.org/project/linux-mm/cover/20210923175347.10727-1-mike.kravetz@oracle.com)
*-*-*-*-*-*-*-*
[2021/10/07 PatchWork v4,0/5](https://patchwork.kernel.org/project/linux-mm/cover/20211007181918.136982-1-mike.kravetz@oracle.com) | +| 2021/10/07 | Mike Kravetz | [hugetlb: add demote/split page functionality](https://lore.kernel.org/patchwork/cover/1465517) | 实现了 hugetlb 降低策略. 提供了一种"就地"将 hugetlb 页面分割为较小的页面的方法. | v4 ☐ | [2021/07/21 PatchWork 0/8](https://patchwork.kernel.org/project/linux-mm/cover/20210721230511.201823-1-mike.kravetz@oracle.com)
*-*-*-*-*-*-*-*
[2021/08/16 PatchWork RESEND,0/8](https://patchwork.kernel.org/project/linux-mm/cover/20210816224953.157796-1-mike.kravetz@oracle.com)
*-*-*-*-*-*-*-*
[2021/09/23 PatchWork v2,0/4](https://patchwork.kernel.org/project/linux-mm/cover/20210923175347.10727-1-mike.kravetz@oracle.com)
*-*-*-*-*-*-*-*
[2021/10/07 PatchWork v4,0/5](https://patchwork.kernel.org/project/linux-mm/cover/20211007181918.136982-1-mike.kravetz@oracle.com) | | 2021/10/14 | Mina Almasry | [mm, hugepages: add mremap() support for hugepage backed vma](https://patchwork.kernel.org/project/linux-mm/patch/20210730221522.524256-1-almasrymina@google.com) | 通过简单地重新定位页表项, 使得 mremap() 支持 hugepage 的 vma 段. 页表条目被重新定位到 mremap() 上的新虚拟地址.
作者验证的测试场景是一个简单的 bench: 它在 hugepages 中重新加载可执行文件的 ELF 文本, 这大大提高了上述可执行文件的执行性能.
将 hugepages 上的 mremap 操作限制为原始映射的大小, 因为底层 hugetlb 保留还不能处理到更大的大小的重映射.
在 mremap () 操作期间, 我们检测 pmd_shared 的映射, 并在 mremap () 期间取消这些映射的共享. 在访问和故障时, 再次建立共享. | v1 ☐ | [PatchWork v1](https://patchwork.kernel.org/project/linux-mm/patch/20210730221522.524256-1-almasrymina@google.com)
*-*-*-*-*-*-*-*
[PatchWork v4,1/2](https://patchwork.kernel.org/project/linux-mm/patch/20211006194515.423539-1-almasrymina@google.com)
*-*-*-*-*-*-*-*
[PatchWork v8,1/2](https://patchwork.kernel.org/project/linux-mm/patch/20211014200542.4126947-1-almasrymina@google.com) | | 2021/09/30 | Baolin Wang | [Support hugetlb charge moving at task migration](https://patchwork.kernel.org/project/linux-mm/cover/cover.1632843268.git.baolin.wang@linux.alibaba.com) | 现在在 hugetlb cgroup 中, 任务迁移时与任务相关的统计不会移动到新的 hugetlb cgroup 中, 这对于 hugetlb cgroup 的使用是奇怪的. 这个补丁集增加了 hugetlb cgroup 中迁移任务时统计信息的迁移. | v1 ☐ | [PatchWork v1](https://patchwork.kernel.org/project/linux-mm/cover/cover.1632843268.git.baolin.wang@linux.alibaba.com) | | 2021/10/05 | Zhenguo Yao | [hugetlbfs: Extend the definition of hugepages parameter to support node allocation](https://lore.kernel.org/patchwork/cover/1479318) | 当前内核允许指定启动时要分配的 hugepages 数目. 但目前所有节点的 hugepages 都是平衡的. 在某些场景中, 我们只需要在一个节点中使用 hugepags.
例如: DPDK 需要与 NIC 位于同一节点的 hugepages. 如果 DPDK 在 node1 中需要 4 个 1G 大小的 HugePage, 并且系统有 16 个 numa 节点. 我们必须在内核 cmdline 中保留 64 个 HugePage. 但是, 只使用了 4 个 hugepages. 其他的应该在引导后释放. 如果系统内存不足(例如: 64G), 这将是一项不可能完成的任务. 因此, 添加 hugepages_node 内核参数以指定启动时要分配的 hugepages 的节点数. | v1 ☐ 5.14-rc7 | [2021/08/20 PatchWork RFC](https://patchwork.kernel.org/project/linux-mm/patch/20210820030536.25737-1-yaozhenguo1@gmail.com)
*-*-*-*-*-*-*-*
[2021/08/23 PatchWork v1](](https://patchwork.kernel.org/project/linux-mm/patch/20210823130154.75070-1-yaozhenguo1@gmail.com)
*-*-*-*-*-*-*-*
[2021/10/05 PatchWork v8](https://patchwork.kernel.org/project/linux-mm/patch/20211005054729.86457-1-yaozhenguo1@gmail.com) | @@ -2383,30 +2384,25 @@ LWN 上 Mel 写的关于 Huge Page 的连载. | 1 | [Memory management/Huge pages](https://lwn.net/Kernel/Index/#Memory_management-Huge_pages) | -### 7.2.1 THP +### 7.2.1 Transparent Hugepage Support ------- 2011 年 v2.6.38 期间 Andrea Arcangeli 为 linux 引入了 THP(Transparent huge page), 在应用需要 huge page 的时候, 可通过内存规整等操作, 为当前 VMA 分配一个 huge page, 因为该过程不会被应用感知到, 所以被称为 "transparent". 参见 [Transparent huge pages in 2.6.38](https://lwn.net/Articles/423584). | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| -| 2010/12/15 | Andrea Arcangeli | [Transparent Hugepage Support #33](https://lore.kernel.org/lkml/20101215051540.GP5638@random.random) | 实现透明大页. | v1 ☑ 2.6.38-rc1 | [LORE](https://lore.kernel.org/lkml/20101215051540.GP5638@random.random), [关键 COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71e3aac0724ffe8918992d76acfe3aad7d872) | +| 2010/12/15 | Andrea Arcangeli | [Transparent Hugepage Support #33](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=a664b2d8555c659127bf8fe049a58449d394a707) | 实现透明大页. | v33 ☑ [2.6.38-rc1](https://kernelnewbies.org/Linux_2_6_38#Transparent_huge_pages) | [LORE](https://lore.kernel.org/lkml/20101215051540.GP5638@random.random), [关键 COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71e3aac0724ffe8918992d76acfe3aad7d872) | 1. 当发生 page fault 时, 内核将尝试使用 [do_huge_pmd_anonymous_page()](https://elixir.bootlin.com/linux/v2.6.38/source/mm/memory.c#L3305) 分配一个 huge page 来满足它. 如果分配成功, huge page 的页表就会被设置, 而该地址范围内的[任何现有的普通页面都将被释放](https://elixir.bootlin.com/linux/v2.6.38/source/mm/memory.c#L3313), 同时将 huge page 插入到进程 VMA 中. 如果没有 huge page 可用, 内核就会通过 [do_huge_pmd_wp_page_fallback()](https://elixir.bootlin.com/linux/v2.6.38/source/mm/huge_memory.c#L910) 退回到普通页面, 应用程序永远不会感知到这些差异. [commit ("71e3aac0724f thp: transparent hugepage core")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71e3aac0724ffe8918992d76acfe3aad7d872). 2. 但是分配时能够分配出 huge page 取决于物理上连续的大的内存块, 这是 Linux 内核程序员永远不能指望的. 因此在一个进程出现若干次小页面的 pge fault 之后, THP 补丁试图通过添加 "khugepaged" 内核线程来改善这种情况. 这个线程偶尔会尝试分配一个巨大的页面; 如果成功, 它会扫描内存, 寻找一个巨大的页面可以替代一堆较小的页面的位置. 因此, 可用的巨大页面应该快速放置到服务中, 最大限度地利用整个系统中的 hugepage. 内核还提供了一整套参数控制 khugepaged 线程的操作. 参见 [commit ("ba76149f47d8 thp: khugepaged")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ba76149f47d8). -3. 同时引入了 defrag 功能, 控制内核是否应该积极地使用内存规整/压缩(compaction) 以使更多的 hugepage 可用. +3. 同时引入了 defrag 功能, 控制内核是否应该积极地使用内存规整/压缩(compaction) 以使更多的 hugepage 可用. 内存规整通过移动页面, 以创建空闲内存中大的、物理上连续的区域. 这些区域通常可以用来支持大量的分配, 对于创建 huge page 来说特别有用. 最早的实现只能用于匿名页面, 将 huge page 与 page cache 集成的工作尚未完成. 它也只处理一个页面大小为(2 MB) 的 PMD level 的大页. 当时 Mel Gorman 运行了一些[基准测试](https://lwn.net/Articles/423590), 在某些情况下可以提高 10% 左右. 一般来说, 结果不如 hugetlbfs 那样好, 但是 THP 更有可能被普遍的运用在生产环境中. - -[Transparent huge page reference counting](https://lwn.net/Articles/619738) - -[THP 和 mapcount 之间的恩恩怨怨](https://richardweiyang-2.gitbook.io/kernel-exploring/00-index/02-thp_mapcount) - 7.1 介绍的这种使用大页的方式看起来是挺怪异的, 需要用户程序做出很多修改. 而且, 内部实现中, 也需要系统预留一大部分内存. 基于此, 2.6.38 引入了一种叫[透明大页 Transparent huge pages](https://lwn.net/Articles/423584) 的实现. 如其名字所示, 这种大页的支持对用户程序来说是透明的. @@ -2426,8 +2422,57 @@ LWN 上 Mel 写的关于 Huge Page 的连载. +### 7.2.2 THP allocations latencies +------- -### 7.2.1 improve THP collapse rate + +THP 虽然实现了, 但是依旧存在着不少问题. 在 LSFMM 2015 进行了讨论, 参见 [Improving huge page handling](https://lwn.net/Articles/636162) + +1. Kirill Shutemov 首先描述了他提出的如何处理透明巨大页面的引用计数的改变, 这个补丁集在 LWN 2014 年 11 月的文章 [Transparent huge page reference counting](https://lwn.net/Articles/619738) 中有详细的描述. 该补丁的关键部分是, 它允许在 PMD (巨大页面)和 PTE (常规页面)模式下同时映射一个巨大的页面. 正如作者所言, 这是一个大的补丁集, 而且仍然存在一些错误, 所以这组补丁并没有被合入主线. 参见 [THP 和 mapcount 之间的恩恩怨怨](https://richardweiyang-2.gitbook.io/kernel-exploring/00-index/02-thp_mapcount). + +2. 剩下的一个问题是关于部分取消巨大页面的映射. 当一个进程取消映射一个 huge page 的一部分页面时, 有多种想法可以执行这种操作. + +| 分割行为 | 描述 | +|:------:|:----:| +| 直接分割 | 将该页面拆分, 并将与释放的区域对应的单个页面返回给系统. | +| 延迟分割 | 也可以将这个 huge page 拆解成普通页面, 但是并不释放它们, 而是内核仍然维护组成这个 huge page 的普通页面, 将它们保持在一起. 这使得 huge page 在需要时允许它快速重新构建. 但是, 这也意味着没有任何内存实际上将被释放, 同时有必要将这个 huge page 及组成它的普通页面添加到一个特殊的列表中, 如果系统遇到内存压力, 可以在该列表中真正地进行分割. | + +3. 最关键的问题在于, 我们分配出的 huge page 是否能带来性能的提升, 不管是处理 page fault 时分配出 huge page, 还是通过 khugepaged 合并出 huge page, 以及通过内存规整整出 huge page. 都是存在开销的. 首先在处理页面 page fault 上进行相当激进的 THP 分配尝试是否是一种良好的性能权衡. 参见 [LSF/MM TOPIC ATTEND](https://marc.info/?l=linux-mm&m=142056088232484&w=2) + + * THP 分配增加了页面错误延迟, 因为高阶分配是出了名的昂贵. 页面分配 slowpath 现在会对 gfp_transshuge && !PF_KTHREAD 进行额外的检查, 以避免对用户页面错误进行更昂贵的同步压缩. 但即使是异步压缩也可能代价高昂. + + * 在 2MB 范围内的第一个 page fault 期间, 我们无法预测该范围内有多少实际将被访问, 理论上我们可以浪费[多达 511 个页面](https://www.spinics.net/lists/kernel/msg1928252.html). 或者, 范围内的页面可以从不同 NUMA 节点的 CPU 访问, 虽然基本页面可以都是本地的, 但 THP 可以远程到除一个 CPU 以外的所有 CPU. 由于这个错误的共享, 远程访问的成本将高于 huge page 省出来的 TLB 的开销. + +因此很多时候, THP 的效果可能远不如想象中那么美好. 比如 SAP 建议为他们的应用程序[禁用 THPs](https://blogs.sap.com/2014/05/22/sap-iq-and-linux-hugepagestransparent-hugepages), 以提高性能. + + +#### 7.2.2.1 Outsourcing THP allocations +------- + +Vlastimil 在 [LSFMM 2015 对 THP 的讨论中](https://lwn.net/Articles/636162) 提到, 由于不可能预测在 page fault 时提供 huge page 的好处, 所以最好少做一些. 相反, 应该主要在 khugepaged 守护进程中创建透明的巨大页面, 该守护进程可以在后台查看内存使用情况和折叠页面. 这样做需要重新设计 khugepaged, 这主要是为了在其他方法失败时填充巨大的页面. 但是它扫描速度很慢, 不能确定一个进程是否会从巨大的页面中受益; 特别是, 它不知道该进程是否会花费大量时间运行. 这可能是因为这个过程大多潜伏着等待外部事件的发生, 也可能是因为它即将退出. + +他的方法是通过将寻找 huge page 机会的扫描工作移动到进程上下文中来改进 khugepaged. 在某些时候, 例如从系统调用返回时, 每个进程都会扫描一部分内存, 或许还会将某些页折叠成 huge page. 它会部分基于成功率自动调整自身, 但也仅仅基于一个进程运行更频繁将做更多的扫描这一事实. 因为不涉及守护进程, 所以不会有额外的唤醒; 如果一个系统完全空闲, 就不会有页面扫描. 不过在 khugepaged 中折叠页面比在 page fault 时分配 huge page 要昂贵得多. + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2014/10/22 | Alex Thorlton | [Convert khugepaged to a task_work function](https://lwn.net/Articles/634384) | 将 huge page 的折叠扫描从 khugepaged 移动到 task_work 上下文. 在这个实现中, 扫描是由 `__khugepaged_enter()` 驱动的, 它在 vma_merge、fork 和 THP page fault 的尝试等事件中被调用, 例如不是完全周期性的事件. | RFC ☐ | [LKML 0/4](https://lkml.org/lkml/2014/10/22/931) | +| 2015/02/23 | Vlastimil Babka | [the big khugepaged redesign](https://lwn.net/Articles/634384) | 解决 huge page
1. 停止在 khugepaged 中预先分配大页面.
2. 只有在我们预期它们会成功的情况下才尝试错误分配.
3. 将折叠从 khugepaged 移动到 task_work 上下文.
4. thp 分配失败时唤醒 khugepaged. | RFC ☐ | [LORE RFC,0/6](https://lore.kernel.org/lkml/1424696322-21952-1-git-send-email-vbabka@suse.cz) | + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2015/05/11 | Vlastimil Babka | [Outsourcing page fault THP allocations to khugepaged](https://lwn.net/Articles/643891) | 由于 [the big khugepaged redesign](https://lwn.net/Articles/634384) 的改动过于激进, 社区建议被拆开重新适配, 将争议最小的一部分先提交到社区. 这组补丁不会将折叠扫描移动到 task_work 上下文, 而是专注于减少回收和压缩在 page fault 上下文中完成的工作, 通过将这一工作转移到 khugepaged. 这有两个好处: | RFC ☐ | [PatchWork RFC,0/4](https://lore.kernel.org/lkml/1431354940-30740-1-git-send-email-vbabka@suse.cz) | + + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2015/07/02 | Vlastimil Babka | [Outsourcing compaction for THP allocations to kcompactd](https://lwn.net/Articles/650051) | NA | RFC ☐ | [PatchWork RFC v2,0/4](https://lore.kernel.org/lkml/1435826795-13777-1-git-send-email-vbabka@suse.cz) | + + + +### 7.2.3 improve THP collapse rate ------- @@ -2442,7 +2487,7 @@ khugepaged 中如果发现当前连续的映射区间内有[超过 `khugepaged_m | 2015/04/14 | Ebru Akagunduz | [mm: incorporate zero pages into transparent huge pages](https://lore.kernel.org/patchwork/cover/541944) | 通过大页允许零页面, 该补丁提高了 THP 的大页转换率. 目前, 当在 2MB 范围内存在最多数量为 khugepaged_max_ptes_none 的 pte_none ptes 时, THP可以将4kB的页面压缩为一个 THP. 这个补丁支持了将零页映射为大页. 该补丁使用一个程序进行测试, 该程序分配了800MB的内存, 并执行交错读写操作, 其模式导致大约2MB的区域首先看到读访问, 从而导致影射了较多的零 pfn 映射. 没有补丁的情况下, 只有 50% 的程序被压缩成THP, 并且百分比不会随着时间的推移而增加. 有了这个补丁, 等待10分钟后, khugepage 转换了 99% 的程序内存. | v2 ☑ [4.1-rc1](https://kernelnewbies.org/Linux_4.1#Memory_management) | [PatchWork v2](https://lore.kernel.org/patchwork/cover/541944), [commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ca0984caa8235762dc4e22c1c47ae6719dcc4064) | | 2015/09/14 | Ebru Akagunduz | [mm: make swapin readahead to gain more THP performance](https://lore.kernel.org/patchwork/cover/597392) | 支持在对匿名页 swapin 的时候 readahead 及逆行大页的转换.
当 khugepaged 扫描页面时, 交换区中可能有一些页面. 有了这个补丁, 当 2MB 范围内 swap_ptes 的数目达到 max_ptes_swap 时, THP 可以将 4kB 页面转换成一个 THP 的大页.
这个补丁用来处理那些在被调出内存后访问大部分(但不是全部)内存的程序的. 补丁合入后, 这些程序不会在内存换出(swapout)后将内存转换成到 THPs 中, 而会在内存从交换分区读入(swapin)时进行转换.
测试使用了用一个测试程序, 该程序分配了 400B 的内存, 写入内存, 然后休眠. 然后强制将所有页面都换出. 之后, 测试程序通过对该内存区域进行写曹祖, 但是它在该区域的每 20 页中跳过一页.
1. 如果没有补丁, 系统就不能在 readahead 中交换. THP率为程序内存的65%, 不随时间变化.
2. 有了这个补丁, 经过10分钟的等待, khugepaged已经崩溃了程序99%的内存. | v2 ☑ [4.8-rc1](https://kernelnewbies.org/Linux_4.8#Memory_management) | [PatchWork RFC,v5,0/3](https://lore.kernel.org/patchwork/cover/597392)
*-*-*-*-*-*-*-*
[PatchWork RFC,v5,0/3](https://lore.kernel.org/lkml/1442259105-4420-1-git-send-email-ebru.akagunduz@gmail.com)
*-*-*-*-*-*-*-*
[LKML](https://lkml.org/lkml/2015/9/14/610) | -### 7.2.2 THP splitting/reclaim/migration +### 7.2.4 THP splitting/reclaim/migration ------- * splitting @@ -2456,8 +2501,8 @@ khugepaged 中如果发现当前连续的映射区间内有[超过 `khugepaged_m | 2018/01/03 | Michal Hocko | [unclutter thp migration](https://lore.kernel.org/patchwork/cover/869414) | THP 迁移以令人惊讶的语义侵入了通用迁移. 迁移分配回调应该检查 THP 是否可以立即迁移, 如果不是这样, 则分配一个简单的页面进行迁移. 取消映射和移动, 然后通过将 THP 拆分为小页面, 同时将标题页面移动到新分配的 order-0 页面来修复此问题. 剩余页面通过拆分页面移动到 LRU 列表. 如果 THP 分配失败, 也会发生同样的情况. 这真的很难看而且容易出错. | v1 ☐ | [PatchWork 0/3](https://lore.kernel.org/patchwork/cover/869414) | | 2020/11/19 | Zi Yan | [Split huge pages to any lower order pages and selftests.](https://patchwork.kernel.org/project/linux-mm/cover/20201119160605.1272425-1-zi.yan@sent.com) | NA | v1 ☐ | [PatchWork 0/7](https://patchwork.kernel.org/project/linux-mm/cover/20201119160605.1272425-1-zi.yan@sent.com) | -* splitting test +* splitting test | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | @@ -2467,7 +2512,7 @@ khugepaged 中如果发现当前连续的映射区间内有[超过 `khugepaged_m -### 7.2.3 Reduce memory bloat +### 7.2.5 Reduce memory bloat ------- 首先是 HZP(huge zero page) 零页的支持. @@ -2504,21 +2549,60 @@ Anthony Yznaga 接替了之前同事 Nitin Gupta 的工作, 并基于 Mel 的思 | 2021/10/28 | Ning Zhang | [Reclaim zero subpages of thp to avoid memory bloat](https://patchwork.kernel.org/project/linux-mm/cover/1635422215-99394-1-git-send-email-ningzhang@linux.alibaba.com) | 这个补丁集引入了一种新的机制来分割没有子页面的大页并回收这些子页面. thp 可能会导致内存膨胀, 从而导致 OOM. 通过对一些应用程序的测试, 作者发现内存膨胀的原因是一个巨大的页面可能包含一些零子页面(可能被访问或没有). 而且大多数零子页面集中在几个大页面中.
通过将匿名大页面添加到列表中, 以减少查找大页面的成本. 当内存回收被触发时, 列表将被遍历, 包含足够的零子页面的大页面可能会被回收. 同时, 用 ZERO_PAGE(0) 替换零子页面. 之前 Yu Zhao 已经做了一些类似的工作 [PatchWork 0/3](https://patchwork.kernel.org/project/linux-mm/cover/20210731063938.1391602-1-yuzhao@google.com), 当巨大的页面被交换或迁移来加速. 当我们在 swap 场景的正常内存收缩路径中这样做时, 以避免 OOM. 未来, 作者可能将尝试主动回收 "冷" 大页面. 为了尽可能在保持 thp 性能的同时. 使得开启了 thp 的内存使用量等于使用普通页的内存使用量. | RFC ☐ | [PatchWork RFC,0/6](https://patchwork.kernel.org/project/linux-mm/cover/1635422215-99394-1-git-send-email-ningzhang@linux.alibaba.com) | -### 7.2.4 THP FS/Page Cache +### 7.2.6 THP Page Cache ------- + [dhowells/linux-fs: fscache-thp](https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=fscache-thp) + +#### 7.2.6.1 THP RAMFS +------- + + | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| | 2013/05/12 | "Kirill A. Shutemov" | [Transparent huge page cache](https://lore.kernel.org/patchwork/cover/378803) | 这组补丁集为内核页面缓存增加了巨页的支持. 为了证明建议的更改是功能性的, 为最简单的文件系统 ramfs 启用了该特性. 每个 THP 在页面缓存基数树中由 HPAGE_PMD_NR(x86-64 上的 512)条目表示: 一个条目用于首页, HPAGE_PMD_NR-1条目用于尾页. 可以通过三种方式将大型页面添加到页面缓存:
1. 向文件或页面写入;
2. 从稀疏文件中读取;
3. 稀疏文件上触发 page_fault.
当然可能存在第三种方法可能是折叠小页面, 但它超出了最初的实现范围. | v4 ☐ | [PatchWork v4,00/39](https://lore.kernel.org/patchwork/cover/378803) | | 2013/09/23 | "Kirill A. Shutemov" | [Transparent huge page cache: phase 1, everything but mmap()](https://lore.kernel.org/patchwork/cover/408000) | 这组补丁集为内核页面缓存增加了巨页的支持. 为了证明建议的更改是功能性的, 为最简单的文件系统 ramfs 启用了该特性, 但是 mmap 除外, 这将在后续的合入中修复. | v4 ☐ | [PatchWork v6,00/22](https://lore.kernel.org/patchwork/cover/408000) | -| 2016/06/15 | "Kirill A. Shutemov" | [THP-enabled tmpfs/shmem](https://lore.kernel.org/patchwork/cover/701302) | 这是我的补丁集的第一个版本, 它旨在将 THO 带到 ext4, 它还没有准备好应用或正式使用, 但足以展示该方法.
基本原理与 tmpfs 相同, 并构建在它的基础上. 主要区别在于, 我们需要处理从备份存储器的读取和回写. | v9 ☑ 4.8-rc1 | [PatchWork v1,RFC,00/33](https://lore.kernel.org/patchwork/cover/658181)
*-*-*-*-*-*-*-*
[PatchWork v9,00/32](https://lore.kernel.org/patchwork/cover/685554)
*-*-*-*-*-*-*-*
[PatchWork v9-rebased2,00/37](https://lore.kernel.org/patchwork/cover/689355) | + + +#### 7.2.6.2 THP TMPFS/SHMEM +------- + + +社区不少开发者在做 (TMPFS) Page Cache 的 THP 支持. 参见 [Two transparent huge page cache implementations](https://lwn.net/Articles/684300) 所述: + +1. 一个解决方案是 Kirill Shutemov 提出的, 他完成了 THP 启用 tmpfs 补丁集. Kirill 的工作基于社区已有的[复合页面 compound pages](https://lwn.net/Articles/619514), 这是一种相当精细的机制, 可以将单个内存页面绑定到一个更大的页面上. 作者个人仓库 [`kas/linux.git`](https://git.kernel.org/pub/scm/linux/kernel/git/kas/linux.git). + +2. 另一个竞争者是由 Hugh Dickins 实现的团队页面(team pages)方案. "团队页面"可以被认为是一种新的、更轻量级的页面分组方式. 它的工作有一个优势, 据作者所言, 这个方案已经在谷歌的产品部署了一年多, 效果和稳定性都有保障. + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2015/02/20 | Hugh Dickins | [huge tmpfs: an alternative approach to THPageCache](https://lwn.net/Articles/634334) | 为 tmpfs 文件系统增加了透明的巨大页面支持.
这项工作包含了页面缓存中完全支持大页面所需的许多元素(这也是 Kirill 补丁的最终目标). 但是 Hugh 的方法相当不同, 这引起了用户社区的一些担忧; 最终, 这些补丁集中只有一个可能被合并.
参见 [Improving huge page handling](https://lwn.net/Articles/636162) | v4 ☐ | [PatchWork 00/24](https://lore.kernel.org/lkml/alpine.LSU.2.11.1502201941340.14414@eggly.anvils) | +| 2016/02/20 | Hugh Dickins | [huge tmpfs: THPagecache implemented by teams](https://lwn.net/Articles/682623) | 为 tmpfs 文件系统增加了透明的巨大页面支持.
这项工作包含了页面缓存中完全支持大页面所需的许多元素(这也是 Kirill 补丁的最终目标). 但是 Hugh 的方法相当不同, 这引起了用户社区的一些担忧; 最终, 这些补丁集中只有一个可能被合并.
参见 [Improving huge page handling](https://lwn.net/Articles/636162) | v4 ☐ | [PatchWork 00/24](https://lore.kernel.org/lkml/alpine.LSU.2.11.1502201941340.14414@eggly.anvils) | + +经过多次改进和优化后, 最终 Kirill Shutemov 的基于复合页的方案 [THP-enabled tmpfs/shmem (using compound pages)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=1b5946a84d6eb096158e535bdb9bda06e7cdd941) 被合入主线 [4.8](https://kernelnewbies.org/Linux_4.8#Support_for_using_Transparent_Huge_Pages_in_the_page_cache) 版本. + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2016/06/15 | "Kirill A. Shutemov" | [THP-enabled tmpfs/shmem (using compound pages)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=1b5946a84d6eb096158e535bdb9bda06e7cdd941) | 支持 tmpfs 和 shmem page cache 的透明大页支持.
1. 引入了 [CONFIG_TRANSPARENT_HUGE_PAGECACHE](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e496cf3d782135c1cca0d154d4b924517ff58de0).
2. 实现了 [shmem page cache 大页](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=800d8c63b2e989c2e349632d1648119bf5862f01)的支持.
3. 完成了 khugepaged [对 tmpfs/shmem page cache 页面合并](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f3f0e1d2150b2b99da2cbdfaad000089efe9bf30)的支持. | v9 ☑ [4.8-rc1](https://kernelnewbies.org/Linux_4.8#Support_for_using_Transparent_Huge_Pages_in_the_page_cache) | [PatchWork v4,00/25](https://lore.kernel.org/patchwork/patch/658181)
*-*-*-*-*-*-*-*
[PatchWork v9,00/32](https://lore.kernel.org/lkml/1465222029-45942-1-git-send-email-kirill.shutemov@linux.intel.com)
*-*-*-*-*-*-*-*
[PatchWork v9-rebased2,00/37](https://lore.kernel.org/lkml/1466021202-61880-1-git-send-email-kirill.shutemov@linux.intel.com) | + + +#### 7.2.6.3 THP EXT4 +------- + + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| | 2016/07/26 | "Kirill A. Shutemov" | [ext4: support of huge pages](https://lore.kernel.org/patchwork/cover/701302) | 这是我的补丁集的第一个版本, 它旨在将 THO 带到 ext4, 它还没有准备好应用或正式使用, 但足以展示该方法.
基本原理与 tmpfs 相同, 并构建在它的基础上. 主要区别在于, 我们需要处理从备份存储器的读取和回写. | RFC,v1 ☐ | [PatchWork v1,RFC,00/33](https://lore.kernel.org/patchwork/cover/701302) | +| 2019/07/17 | Yang Shi | [Fix false negative of shmem vma's THP eligibility](https://lore.kernel.org/patchwork/cover/1101422) | 提交7635d9cbe832 ("mm, THP, proc: report THP qualified for each vma") 为进程的 map 引入了 THPeligible bit. 但是, 当检查 shmem vma 的资格时, `__transparent_hugepage_enabled()` 被调用以覆盖来自 shmem_huge_enabled() 的结果. 它可能导致匿名 vma 的 THP 标志覆盖 shmem 的.
通过使用 transhuge_vma_suitable() 来检查 vma, 来修复此问题 | v4 ☑ 5.3-rc1 | [PatchWork v4,0/2](https://lore.kernel.org/patchwork/cover/1101422) | | 2021/07/30 | Hugh Dickins | [tmpfs: HUGEPAGE and MEM_LOCK fcntls and memfds](https://patchwork.kernel.org/project/linux-mm/cover/2862852d-badd-7486-3a8e-c5ea9666d6fb@google.com) | 一系列 HUGEPAGE 和 MEM_LOCK tmpfs fcntls 和 memfd_create 标志的清理和修复工作. | v1 ☐ | [PatchWork 00/16](https://patchwork.kernel.org/project/linux-mm/cover/2862852d-badd-7486-3a8e-c5ea9666d6fb@google.com) | +#### 7.2.6.4 non-tmpfs filesystems +------- -Matthew Wilcox (Oracle) 在这方面也做了很多工作. +Matthew Wilcox 在这方面也做了很多工作. 代码仓库参见 : http://git.infradead.org/users/willy/pagecache.git | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | @@ -2533,15 +2617,7 @@ Matthew Wilcox (Oracle) 在这方面也做了很多工作. | 2020/10/29 | "Matthew Wilcox (Oracle)" | [Transparent Hugepages for non-tmpfs filesystems](https://patchwork.kernel.org/project/linux-mm/cover/2862852d-badd-7486-3a8e-c5ea9666d6fb@google.com) | 一系列 HUGEPAGE 和 MEM_LOCK tmpfs fcntls 和 memfd_create 标志的清理和修复工作. | v1 ☐ | [PatchWork 00/16](https://patchwork.kernel.org/project/linux-mm/cover/20201029193405.29125-1-willy@infradead.org) | -### 7.2.5 THP SHMEM -------- - -| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | -|:----:|:----:|:---:|:----:|:---------:|:----:| -| 2019/07/17 | Yang Shi | [Fix false negative of shmem vma's THP eligibility](https://lore.kernel.org/patchwork/cover/1101422) | 提交7635d9cbe832 ("mm, THP, proc: report THP qualified for each vma") 为进程的 map 引入了 THPeligible bit. 但是, 当检查 shmem vma 的资格时, `__transparent_hugepage_enabled()` 被调用以覆盖来自 shmem_huge_enabled() 的结果. 它可能导致匿名 vma 的 THP 标志覆盖 shmem 的.
通过使用 transhuge_vma_suitable() 来检查 vma, 来修复此问题 | v4 ☑ 5.3-rc1 | [PatchWork v4,0/2](https://lore.kernel.org/patchwork/cover/1101422) | - - -### 7.2.5 khugepaged +### 7.2.7 khugepaged ------- khugepaged 是透明巨页的守护进程, 它会被定时唤醒, 并根据配置尝试将 page_size(比如 4K) 大小的普通 page 转成巨页, 减少 TLB 压力, 提高内存使用效率. @@ -2587,7 +2663,7 @@ khugepaged 处理流程 | 2015/09/14 | Ebru Akagunduz | [mm: add tracepoint for scanning pages](https://lkml.org/lkml/2015/9/14/611) | [mm: make swapin readahead to gain more THP performance](https://lore.kernel.org/lkml/1442259105-4420-1-git-send-email-ebru.akagunduz@gmail.com) 系列的其中一个补丁, 为 khuagepaged 引入了 tracepoint 跟踪点. 用 scan_result 标记了 khugepaged 扫描的结果. | v5 ☑ 4.5-rc1 | [PatchWork RFC,v5,0/3](https://lore.kernel.org/lkml/1442259105-4420-2-git-send-email-ebru.akagunduz@gmail.com)
*-*-*-*-*-*-*-*
[LKML](https://lkml.org/lkml/2015/9/14/611)
*-*-*-*-*-*-*-*
[commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7d2eba0557c18f7522b98befed98799990dd4fdb) | | 2011/01/13 | Peter Xu | [mm/khugepaged: Detecting uffd-wp vma more efficiently](https://patchwork.kernel.org/project/linux-mm/patch/20210922175156.130228-1-peterx@redhat.com) | 实现了一个 khugepaged 的内核线程, 用来完成将标准的小页面合并成大页的操作. | ☑ 2.6.38-rc1 | [commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ba76149f47d8c939efa0acc07a191237af900471) | -### 7.2.6 优化 struct page 的内存占用 +### 7.2.8 优化 struct page 的内存占用 -------- * DMEMFS @@ -2991,7 +3067,7 @@ git://github.com/glommer/linux.git kmemcg-slab | 2011/12/08 | Johannes Weiner | [memcg naturalization -rc5](https://lore.kernel.org/patchwork/cover/273527) | 引入 per-memcg lru, 消除重复的 LRU 列表, [全局 LRU 不再存在, page 只存在于 per-memcg LRU list 中](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=925b7673cce39116ce61e7a06683a4a0dad1e72a).
它使传统的页面回收能够从每个memcg LRU列表中查找页面, 从而消除了双LRU模式(除了每个memcg区域外, 每个全局区域)和系统中每个页面所需的额外列表头.
该补丁引入了 lruvec 结构. | v5 ☑ [3.3-rv1](https://kernelnewbies.org/Linux_3.3#Memory_management) | [PatchWork v5](https://lore.kernel.org/patchwork/cover/273527), [LWN](https://lwn.net/Articles/443241) | | 2012/02/20 | Hugh Dickins | [mm/memcg: per-memcg per-zone lru locking](https://lore.kernel.org/patchwork/cover/288055) | per-memcg lru lock | v1 ☐ | [PatchWork v1](https://lore.kernel.org/patchwork/cover/288055) | | 2020/12/05 | Alex Shi | [per memcg lru lock](https://lore.kernel.org/patchwork/cover/1333353) | per memcg LRU lock | v21 ☑ [5.11](https://kernelnewbies.org/Linux_5.11#Memory_management) | [PatchWork v21](https://lore.kernel.org/patchwork/cover/1333353) | -| 2011/05/26 | KAMEZAWA Hiroyuki | [memcg async reclaim](https://lore.kernel.org/patchwork/cover/251835) | 实现 MEMCG 的异步回收机制(Asynchronous memory reclaim)
1. 当使用 memc g时, 应用程序可以看到由 memcg 限制引起的内存回收延迟. 一般来说, 这是不可避免的. 有一类应用程序, 它使用许多干净的文件缓存并执行一些交互式工作.
2. 如果内核能够帮助后台回收内存, 那么应用程序的延迟就会在一定程度上被隐藏(这取决于应用程序的睡眠方式). 这组补丁程序添加了控制开关 memory.async_control 启用异步回收. 采用动态计算的方法计算了边缘的大小. 该值被确定为减少应用程序达到限制的机会.
使用了新引入的 WQ_IDLEPRI 类型(使用 SCHED_IDLE 调度策略)的 kworker(memcg_async_shrinker) 来完整回收的操作. 通过使用SCHED_IDLE, 系统繁忙的时候异步内存回收只能消耗 0.3% 的 CPU, 但如果cpu空闲, 可以使用很多cpu. | v3 ☐ | [PatchWork RFC,v3,0/10](https://lore.kernel.org/patchwork/cover/251835) | +| 2011/05/26 | KAMEZAWA Hiroyuki | [memcg async reclaim](https://lore.kernel.org/patchwork/cover/251835) | 实现 MEMCG 的异步回收机制(Asynchronous memory reclaim)
1. 当使用 memc g时, 应用程序可以看到由 memcg 限制引起的内存回收延迟. 一般来说, 这是不可避免的. 有一类应用程序, 它使用许多干净的文件缓存并执行一些交互式工作.
2. 如果内核能够帮助后台回收内存, 那么应用程序的延迟就会在一定程度上被隐藏(这取决于应用程序的睡眠方式). 这组补丁程序添加了控制开关 memory.async_control 启用异步回收. 采用动态计算的方法计算了边缘的大小. 该值被确定为减少应用程序达到限制的机会.
使用了新引入的 WQ_IDLEPRI 类型(使用 SCHED_IDLE 调度策略)的 kworker(memcg_async_shrinker) 来完整回收的操作. 通过使用 SCHED_IDLE, 系统繁忙的时候异步内存回收只能消耗 0.3% 的 CPU, 但如果cpu空闲, 可以使用很多cpu. | v3 ☐ | [PatchWork RFC,v3,0/10](https://lore.kernel.org/patchwork/cover/251835) | | 2017/05/30 | Johannes Weiner | [mm: per-lruvec slab stats](https://lore.kernel.org/patchwork/cover/793422) | Josef 正在研究一种平衡 slab 缓存和 page cache 的新方法. 为此, 他需要 lruvec 级别的 slab 缓存统计信息. 这些补丁通过添加基础设施来实现这一点, 该基础设施允许每个 lruvec 更新和读取通用 VM 统计项, 然后将一些现有VM记帐站点(包括slab记帐站点)切换到这个新的 cgroup 感知 API. | v1 ☑ 4.13-rc1 | [PatchWork 0/6](https://lore.kernel.org/patchwork/cover/793422) | | 2021/02/17 | Yang Shi | [Make shrinker's nr_deferred memcg aware](https://lore.kernel.org/patchwork/cover/1393744) | 最近, 在一些 vfs 元数据繁重的工作负载上看到了大量的 one-off slab drop, 造成收缩器了大量累积的 nr_deferred 对象.
这个是由多种原因导致的.
这组补丁集使 nr_deferred 变成 per-memcg 来解决问题. | v10 ☑ 5.13-rc1 | [PatchWork v10,00/13](https://patchwork.kernel.org/project/linux-mm/cover/20210217001322.2226796-1-shy828301@gmail.com) | | 2021/10/19 | Huangzhaoyang | [mm: skip current when memcg reclaim](https://patchwork.kernel.org/project/linux-mm/patch/1634628576-27448-1-git-send-email-huangzhaoyang@gmail.com) | NA | v2 ☐ | [PatchWork v1](https://patchwork.kernel.org/project/linux-mm/patch/1634278529-16983-1-git-send-email-huangzhaoyang@gmail.com)
*-*-*-*-*-*-*-*
[PatchWork v2](https://patchwork.kernel.org/project/linux-mm/patch/1634628576-27448-1-git-send-email-huangzhaoyang@gmail.com) | @@ -3670,11 +3746,11 @@ DAMON 利用两个核心机制 : **基于区域的采样**和**自适应区域 | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| -| 2021/07/16 | SeongJae Park / | [Introduce Data Access MONitor (DAMON)](https://damonitor.github.io) | 数据访问监视器 DAMON | v34 ☑ 5.15-rc1 | [PatchWork v24,00/14](https://lore.kernel.org/patchwork/cover/1375732), [LWN](https://lwn.net/Articles/1461471)
*-*-*-*-*-*-*-*
[PatchWork v34,00/13](https://patchwork.kernel.org/project/linux-mm/cover/20210716081449.22187-1-sj38.park@gmail.com) | +| 2021/07/16 | SeongJae Park / | [Introduce Data Access MONitor (DAMON)](https://damonitor.github.io) | 数据访问监视器 DAMON | v34 ☑ [5.15-rc1](https://kernelnewbies.org/LinuxChanges#Linux_5.15.DAMON.2C_a_data_access_monitor) | [PatchWork v24,00/14](https://lore.kernel.org/patchwork/cover/1375732), [LWN](https://lwn.net/Articles/1461471)
*-*-*-*-*-*-*-*
[PatchWork v34,00/13](https://patchwork.kernel.org/project/linux-mm/cover/20210716081449.22187-1-sj38.park@gmail.com) | | 2021/10/19 | SeongJae Park | [Introduce DAMON-based Proactive Reclamation](https://lwn.net/Articles/863753) | 该补丁集改进了用于生产质量的通用数据访问模式内存管理的引擎, 并在其之上实现了主动回收. | v4 ☑ 5.16-rc1 | [PatchWork RFC,00/13](https://patchwork.kernel.org/project/linux-mm/cover/20210720131309.22073-1-sj38.park@gmail.com)
*-*-*-*-*-*-*-*
[PatchWork RFC,v2,00/14](https://patchwork.kernel.org/project/linux-mm/patch/20210608115254.11930-15-sj38.park@gmail.com)
*-*-*-*-*-*-*-*
[PatchWork RFC,v3,00/15](https://patchwork.kernel.org/project/linux-mm/cover/20210720131309.22073-1-sj38.park@gmail.com)
*-*-*-*-*-*-*-*
[PatchWork v4 00/15](https://patchwork.kernel.org/project/linux-mm/cover/20211019150731.16699-1-sj@kernel.org) | | 2021/08/31 | SeongJae Park // | [mm/damon/vaddr: Safely walk page table](https://patchwork.kernel.org/project/linux-mm/patch/20210831161800.29419-1-sj38.park@gmail.com) | 提交 linux-mm 的 [3f49584b262c ("mm/damon: implement primitives for the virtual memory address spaces")](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f49584b262c) 尝试使用 follow_invalidate_PTE() 查找任意虚拟地址的 PTE 或 PMD, 但没有正确锁定. 此提交通过在正确的锁定(保持 mmap 读取锁定)下使用另一个页面表遍历函数来解决此问题, 并使用了更通用的 walk_page_range(). | v1 ☐ | [PatchWork v2](https://patchwork.kernel.org/project/linux-mm/patch/20210831161800.29419-1-sj38.park@gmail.com) | | 2021/09/17 | SeongJae Park | [mm, mm/damon: Trivial fixes](https://patchwork.kernel.org/project/linux-mm/cover/20210917123958.3819-1-sj@kernel.org) | DAMON 的 fix 补丁. | v1 ☐ | [PatchWork 0/5](https://patchwork.kernel.org/project/linux-mm/cover/20210917123958.3819-1-sj@kernel.org) | -| 2021/10/01 | SeongJae Park | [Implement Data Access Monitoring-based Memory Operation Schemes](https://patchwork.kernel.org/project/linux-mm/cover/20211001125604.29660-1-sj@kernel.org) | 实现了 DAMON 的基于数据访问监视的操作方案 (DAMOS).
DAMON 可以用作支持数据访问的内存管理优化的原语. 因此, 希望进行此类优化的用户应该运行 DAMON, 读取监视结果, 分析并优化内存管理方案.
然而, 在许多其他情况下, 用户只是希望系统对具有特定时间的特定访问频率的特定大小的内存区域应用内存管理操作. 例如, “page out a memory region than 100mib only rare visits more than 2 minutes”, 或者 “Do not use THP For a memory region than 2mib rarely visits more than 1 seconds”. 为了使工作更容易且不冗余, 这个补丁集实现了 DAMON 的一个新特性, 称为基于数据访问监视的操作方案 (DAMOS). 使用该特性, 用户可以以简单的方式描述常规方案, 并要求 DAMON 自行执行这些方案.
DAMOS 对于内存管理优化是准确和有用的.
1. THP 的一个实验性的基于 damon 的操作方案 'ethp' 减少了 76.15% 的 THP 内存开销, 同时保留了 51.25% 的 THP 加速.
2. 另一个实验性的基于 damon 的 "主动回收" 实现 "prcl", 减少了 93.38% 的 residential sets 和 23.63% 的内存占用, 而在最好的情况下只产生 1.22% 的运行时开销 (parsec3/freqmine). | v1 ☑ 5.16-rc1 | [2020/12/16 PatchWork RFC,v15.1,0/8](https://patchwork.kernel.org/project/linux-mm/cover/20201216084404.23183-1-sjpark@amazon.com)
*-*-*-*-*-*-*-*
[2021/10/01 PatchWork 0/7](https://patchwork.kernel.org/project/linux-mm/cover/20211001125604.29660-1-sj@kernel.org) | +| 2021/10/01 | SeongJae Park | [Implement Data Access Monitoring-based Memory Operation Schemes](https://patchwork.kernel.org/project/linux-mm/cover/20211001125604.29660-1-sj@kernel.org) | 实现了 DAMON 的基于数据访问监视的操作方案 (DAMOS).
DAMON 可以用作支持数据访问的内存管理优化的原语. 因此, 希望进行此类优化的用户应该运行 DAMON, 读取监视结果, 分析并优化内存管理方案.
然而, 在许多其他情况下, 用户只是希望系统对具有特定时间的特定访问频率的特定大小的内存区域应用内存管理操作. 例如, "page out a memory region than 100mib only rare visits more than 2 minutes", 或者 "Do not use THP For a memory region than 2mib rarely visits more than 1 seconds". 为了使工作更容易且不冗余, 这个补丁集实现了 DAMON 的一个新特性, 称为基于数据访问监视的操作方案 (DAMOS). 使用该特性, 用户可以以简单的方式描述常规方案, 并要求 DAMON 自行执行这些方案.
DAMOS 对于内存管理优化是准确和有用的.
1. THP 的一个实验性的基于 damon 的操作方案 'ethp' 减少了 76.15% 的 THP 内存开销, 同时保留了 51.25% 的 THP 加速.
2. 另一个实验性的基于 damon 的 "主动回收" 实现 "prcl", 减少了 93.38% 的 residential sets 和 23.63% 的内存占用, 而在最好的情况下只产生 1.22% 的运行时开销 (parsec3/freqmine). | v1 ☑ 5.16-rc1 | [2020/12/16 PatchWork RFC,v15.1,0/8](https://patchwork.kernel.org/project/linux-mm/cover/20201216084404.23183-1-sjpark@amazon.com)
*-*-*-*-*-*-*-*
[2021/10/01 PatchWork 0/7](https://patchwork.kernel.org/project/linux-mm/cover/20211001125604.29660-1-sj@kernel.org) | | 2021/10/08 | SeongJae Park | [mm/damon/dbgfs: Implement recording feature](https://patchwork.kernel.org/project/linux-mm/patch/20211008094509.16179-1-sj@kernel.org) | 为 'damon-dbgfs' 实现 'recording' 特性
用户空间可以通过 'damon_aggregate' 跟踪点事件获得监视结果. 为了简单起见, 跟踪点事件有一些重复的信息, 比如 'target_id' 和 'nr_regions'. 这造成它的大小比实际需要的要大. 另外, 对于一些简单的用例, 处理跟踪点可能会很复杂. 为了给用户空间提供一种更有效和简单的监控结果的方法, 这个提交实现了 'damon-dbgfs' 中的 'recording' 特性. 该特性通过一个名为 'record' 的新 debugfs 文件导出到用户空间, 该文件位于 '/damon/' 目录下. 该文件允许用户以简单格式在常规二进制文件中记录监视的访问模式. 记录的结果首先写入内存缓冲区并批处理刷新到文件中. 用户可以通过读取和写入 record 文件来获取和设置缓冲区的大小和结果文件的路径. | v1 ☐ | [PatchWork 1/4](https://patchwork.kernel.org/project/linux-mm/patch/20211008094509.16179-1-sj@kernel.org) | | 2021/10/12 | SeongJae Park | [DAMON: Support Physical Memory Address Space Monitoring](https://www.phoronix.com/scan.php?page=news_item&px=DAMON-Physical-Monitoring) | 允许物理地址空间监控. | v1 ☑ 5.16-rc1 | [PatchWork RFC,v9,00/10](https://patchwork.kernel.org/project/linux-mm/cover/20201007071409.12174-1-sjpark@amazon.com)
*-*-*-*-*-*-*-*
[PatchWork RFC,v10,00/13](https://patchwork.kernel.org/project/linux-mm/cover/20201216094221.11898-1-sjpark@amazon.com))
*-*-*-*-*-*-*-*
[PatchWork 0/7](https://patchwork.kernel.org/project/linux-mm/cover/20211012205711.29216-1-sj@kernel.org)| | 2021/10/12 | Xin Hao | [mm/damon/dbgfs: add region_stat interface](https://patchwork.kernel.org/project/linux-mm/patch/20211012054948.90381-1-xhao@linux.alibaba.com) | DAMON 中使用 damon-dbgfs 操作带来了很大的便利, 有时候如果我希望能够查看任务的划分区域 nr_access 等值, 当前这不能直接通过 dbgfs 接口查看, 所以添加一个接口 "region_stat" 来显示. | v1 ☐ | [PatchWork](https://patchwork.kernel.org/project/linux-mm/patch/20211012054948.90381-1-xhao@linux.alibaba.com/) | diff --git a/study/kernel/00-DESCRIPTION/SCHEDULER.md b/study/kernel/00-DESCRIPTION/SCHEDULER.md index afd3f30..79caffd 100644 --- a/study/kernel/00-DESCRIPTION/SCHEDULER.md +++ b/study/kernel/00-DESCRIPTION/SCHEDULER.md @@ -271,7 +271,7 @@ SCHED_IDLE 跟 SCHED_BATCH 一样, 是 CFS 中的一个策略, SCHED\_IDLE 的 | 2019/10/24 | NA | [sched/fair: Make sched-idle cpu selection consistent throughout 1143783 diffmboxseries](https://lore.kernel.org/patchwork/patch/1143783) | 重构了 SCHED_IDLE 时的选核逻辑, 所有的选核流程都将 avaliable_idle_cpu 和 sched_idle_cpu 同等对待 | v1 ☑ 5.4-rc1 | [PatchWork](https://lore.kernel.org/patchwork/patch/1143783) | | 2020/12/23 | NA | [sched/fair: Load balance aggressively for SCHED_IDLE CPUs](https://lkml.org/lkml/2020/1/8/112) | LOAD_BALANCE 感知 SCHED_IDLE 优化, SCHED_IDLE 的 CPU 虽然运行着进程但是在调度器看来其实也是空闲的, 应该积极地进行负载均衡 | v1 ☑ 5.6-rc1 | [LKML](https://lkml.org/lkml/2020/1/8/112) | | 2021/02/22 | NA | [sched: pull tasks when CPU is about to run SCHED_IDLE tasks](https://lore.kernel.org/patchwork/patch/1382990) | 在 CPU 从 SCHED_NORMAL 进程切换到 SCHED_IDLE 任务之前, 尝试通过 load_balance 从其他核上 PULL SCHED_NORMAL 进程过来执行. | v2 | [2020/12/27 v1](https://lore.kernel.org/patchwork/patch/1356241), [2021/02/22 v2](https://lore.kernel.org/patchwork/patch/1143783) | -| 2021/08/20 | Josh Don |[cgroup SCHED_IDLE support/SCHED_IDLE extensions](https://lore.kernel.org/patchwork/patch/1443542) | 1. cgroup [组支持 SCHED_IDLE](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=304000390f88)
2. RQ 上维护了 [idle_nr_running](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a480addecc0d) 的跟踪.
3. 引入 [`sysctl_sched_idle_min_granularity`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=51ce83ed523b), 当 SCHED_IDLE 任务与正常任务竞争时适用, 表示 SCHED_IDLE 任务的最小抢占粒度. 这样在与普通实体竞争时, 通过对 SCHED_IDLE 的调度实体使用较小的、无伸缩性的最小抢占粒度(由 sched_slice 计算). 可以减少普通调度实体切回来的延迟, 但代价是增加了SCHED_IDLE实体的上下文切换频率. 有效地减少了普通调度实体在与 SCHED_IDLE 调度实体竞争时的轮询延迟.
4. 在 place_entity() 中对于 `SCHED_IDLE` 实体唤醒时得到的补偿减少到 `sysctl_sched_min_granularity`. 因此, 唤醒的 SCHED_IDLE 实体将花费更长的时间来抢占正常实体. 此更改的好处是, 降低了新唤醒的 `SCHED_IDLE` 实体在阻塞之前抢占短期运行的普通调度实体的可能性. | v1 ☑ 5.16 | [2021/06/08 v1](https://lore.kernel.org/lkml/20210608231132.32012-1-joshdon@google.com)
*-*-*-*-*-*-*-*
[2021/7/29 LKML v2 0/2](https://lkml.org/lkml/2021/7/29/1201)
*-*-*-*-*-*-*-*
[2021/08/20 LORE v3,0/4](https://lore.kernel.org/all/20210820010403.946838-1-joshdon@google.com)
*-*-*-*-*-*-*-*
[关键 commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=304000390f88d049c85e9a0958ac5567f38816ee) | +| 2021/08/20 | Josh Don |[cgroup SCHED_IDLE support/SCHED_IDLE extensions](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=304000390f88d049c85e9a0958ac5567f38816ee) | 1. cgroup [组支持 SCHED_IDLE](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=304000390f88)
2. RQ 上维护了 [idle_nr_running](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a480addecc0d) 的跟踪.
3. 引入 [`sysctl_sched_idle_min_granularity`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=51ce83ed523b), 当 SCHED_IDLE 任务与正常任务竞争时适用, 表示 SCHED_IDLE 任务的最小抢占粒度. 这样在与普通实体竞争时, 通过对 SCHED_IDLE 的调度实体使用较小的、无伸缩性的最小抢占粒度(由 sched_slice 计算). 可以减少普通调度实体切回来的延迟, 但代价是增加了SCHED_IDLE实体的上下文切换频率. 有效地减少了普通调度实体在与 SCHED_IDLE 调度实体竞争时的轮询延迟.
4. 在 place_entity() 中对于 `SCHED_IDLE` 实体唤醒时得到的补偿减少到 `sysctl_sched_min_granularity`. 因此, 唤醒的 SCHED_IDLE 实体将花费更长的时间来抢占正常实体. 此更改的好处是, 降低了新唤醒的 `SCHED_IDLE` 实体在阻塞之前抢占短期运行的普通调度实体的可能性. | v3 ☑ [5.15-rc1](https://kernelnewbies.org/LinuxChanges#Linux_5.15.cgroup_support_for_SCHED_IDLE) | [2021/06/08 v1](https://lore.kernel.org/lkml/20210608231132.32012-1-joshdon@google.com)
*-*-*-*-*-*-*-*
[2021/7/29 LKML v2 0/2](https://lkml.org/lkml/2021/7/29/1201)
*-*-*-*-*-*-*-*
[2021/08/20 LORE v3,0/4](https://lore.kernel.org/all/20210820010403.946838-1-joshdon@google.com)
*-*-*-*-*-*-*-*
[关键 commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=304000390f88d049c85e9a0958ac5567f38816ee) | ### 1.1.6 吭哧吭哧跑计算 SCHED\_BATCH @@ -504,15 +504,36 @@ coscheduling 协同调度是为了解决云服务场景, 为不同用户提供 2.6.23 引入的 CFS 调度器对所有进程完全公平对待. 但这有个问题, 设想当前机器有2个用户, 有一个用户跑着 9个进程, 还都是 CPU 密集型进程; 另一个用户只跑着一个 X 进程, 这是交互性进程. 从 CFS 的角度看, 它将平等对待这 10 个进程, 结果导致的是跑 X 进程的用户受到不公平对待, 他只能得到约 10% 的 CPU 时间, 让他的体验相当差. -基于此, 组调度的概念被引入[6](#refer-anchor-6). CFS 处理的不再是一个进程的概念, 而是调度实体(sched entity), 一个调度实体可以只包含一个进程, 也可以包含多个进程. 因此, 上述例子的困境可以这么解决: 分别为每个用户建立一个组, 组里放该用户所有进程, 从而保证用户间的公平性. +基于此, [组调度](https://lwn.net/Articles/240474)的概念被引入. CFS 处理的不再是一个进程的概念, 而是调度实体(sched entity), 一个调度实体可以只包含一个进程, 也可以包含多个进程. 因此, 上述例子的困境可以这么解决: 分别为每个用户建立一个组, 组里放该用户所有进程, 从而保证用户间的公平性. -该功能是基于控制组(control group, cgroup)的概念, 需要内核开启 CGROUP 的支持才可使用. 关于 CGROUP, 以后可能会写. +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2007/06/23 | Ingo Molnar | [Add group awareness to CFS - v2](https://lwn.net/Articles/239619) | 实现 CFS 组调度. | v2 ☑ 2.6.23 | [LWN](https://lwn.net/Articles/239619) | -### 2.1.2 CFS BANDWIDTH 带宽控制 +该功能是基于控制组(control group, cgroup)的概念, 需要内核开启 CGROUP 的支持才可使用. + + +### 2.1.2 autogroup ------- -内核中的 `CFS BANDWIDTH Controller` 是控制每个 CGROUP 可以使用多少 CPU 时间的一种有效方式. 它可以避免某些进程消耗过多的 CPU 时间, 并确保所有需要 CPU 的进程都能拿到足够的时间. +CFS 用户反复在社区抱怨并行 kbuild 对桌面交互性有负面影响, 因此 Linus 提出了一个想法 autogroup, 即自动创建任务组. +[Group scheduling and alternatives](https://lwn.net/Articles/418884) + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2010/12/05 | Con Kolivas | [sched: automated per session task groups](https://lwn.net/Articles/239619) | 实现 CFS 组调度. | v4 ☑ [2.6.38-rc1](https://kernelnewbies.org/2.6.38-rc1#Automatic_process_grouping_.28a.k.a._.22the_patch_that_does_wonders.22.29) | [LWN](https://lwn.net/Articles/239619), [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5091faa449ee0b7d73bc296a93bca9540fc51d0a) | + + +### 2.1.3 CFS BANDWIDTH 带宽控制 +------- + +内核中的 [`CFS BANDWIDTH Controller`](https://lwn.net/Articles/428230) 是控制每个 CGROUP 可以使用多少 CPU 时间的一种有效方式. 它可以避免某些进程消耗过多的 CPU 时间, 并确保所有需要 CPU 的进程都能拿到足够的时间. + +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 |368685 +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2010/01/05 | Paul Turner | [CFS Hard limits - v5](https://lwn.net/Articles/368685) | 实现 CFS 组调度. | v5 ☐ | [LWN v5,0/8](https://lwn.net/Articles/368685) | +| 2011/02/15 | Paul Turner | [CFS Bandwidth Control: Introduction](https://lwn.net/Articles/428175) | 实现 CFS 组调度. | v2 ☑ 2.6.23 | [LWN](https://lwn.net/Articles/428175) | 这个 bandwidth controller 提供了两个参数来管理针对各个 cgroup 的限制. @@ -1277,6 +1298,9 @@ ARM 的 Morten Rasmussen 一直致力于ANDROID 调度器优化的: |:----:|:----:|:---:|:---:|:----------:|:----:| | 2016/10/14 | Vincent Guittot | [sched: Clean-ups and asymmetric cpu capacity support](https://lore.kernel.org/patchwork/cover/725608) | 调度程序目前在非对称计算能力的系统上没有做太多的工作来提高性能(读ARM big.LITTLE). 本系列主要通过对任务唤醒路径进行一些调整来改善这种情况, 这些调整主要考虑唤醒时的计算容量, 而不仅仅考虑cpu对这些系统是否空闲. 在部分使用的场景中, 这为我们提供了一致的、可能更高的吞吐量. SMP的行为和性能应该是不受影响.
注意这组补丁是分批合入的 | v1 ☑ 4.10-rc1 | [PatchWork](https://lore.kernel.org/patchwork/cover/725608) | | 2021/06/03 | Valentin Schneider | [Rework CPU capacity asymmetry detection](https://lore.kernel.org/patchwork/cover/1424708) | 当前版本 asym_cpu_capacity_level 存在几个问题.
1. 只能支持到最低的拓扑级别, 对全局的拓扑域不可见.
2. 不支持 NUMA 级别的异构, 因为初始化 NUMA 级别的 sd_numa_mask 中不包含其他 NODE, 最终 sched_domain_span 是在构建调度域的时候进行的更新的.
这对于大多数现有的不对称设计很实用, 但是却不支持普适的性能异构架构.这可能不是最好的方法, 在一些领域可能看不到任何不对称. 这对于不合适的迁移和能量感知的安置可能会有问题. 因此, 对于受影响的平台, 它可能导致对唤醒和 CPU 选择路径的自定义更改.
这组补丁修改了执行非对称检测的方式, 允许将非对称拓扑级别固定在最低的拓扑级别上, 在最低的拓扑级别上, 给定调度域中的所有 CPU 都可以看到整个 CPU 容量范围. asym_cpu_capacity_level 还将跟踪那些观察到任何非对称范围的级别, 以使用 SD_ASYM_CPUCAPACITY 标志表示相应的调度域, 并为这些域启用不匹配迁移. 为了区分局部和全范围 CPU 容量不对称的调度域, 引入了新的调度域标志: SD_ASYM_CPUCAPACITY_FULL. | v7 ☑ 5.14-rc1 | [PatchWork v1](https://lore.kernel.org/patchwork/cover/1414557)
*-*-*-*-*-*-*-*
[PatchWork v7](https://lore.kernel.org/all/20210603140627.8409-1-beata.michalska@arm.com) | +| 2021/07/30 | Will Deacon | [Add support for 32-bit tasks on asymmetric AArch32 systems](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/?id=702f43872665) | 一些体系结构, 特别是 ARM, 配置了一些 CPU 支持传统的 32 位应用程序, 但是一些 CPU 只支持 64 位. 这组补丁增加了对 32 位程序调度的支持, 这些 32 位的程序只能在支持传统 32 位任务的 CPU 中执行. | v1 ☑ [5.15-rc1](https://kernelnewbies.org/LinuxChanges#Linux_5.15.Support_for_asymmetric_scheduling_affinity) | [PatchWork v11,00/16](https://lore.kernel.org/all/20210730112443.23245-1-will@kernel.org) | + + * capacity aware wakeup