diff --git a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md index ec9a1c3..c293b5b 100644 --- a/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md +++ b/study/kernel/00-DESCRIPTION/MEMORY_MANAGER.md @@ -1421,7 +1421,7 @@ Mel Gorman 观察到, 所有使用的内存页有三种情形: | 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | |:----:|:----:|:---:|:----:|:---------:|:----:| -| 2009/06/11 | Mel Gorman | [Fix malloc() stall in zone_reclaim() and bring behaviour more in line with expectations V3](https://lore.kernel.org/patchwork/patch/159963) | NA | v1 ☑ v2.6.16-rc2 | [PatchWork](https://lore.kernel.org/patchwork/cover/159963) | +| 2009/06/11 | Mel Gorman | [Fix malloc() stall in zone_reclaim() and bring behaviour more in line with expectations V3](https://lore.kernel.org/patchwork/patch/159963) | NA | v1 ☑ v2.6.16-rc2 | [PatchWork](https://lore.kernel.org/patchwork/cover/159963), [LKML](https://lkml.org/lkml/2009/6/11/143) | | 2015/09/21 | Mel Gorman | [remove zonelist cache and high-order watermark checking v4](https://lore.kernel.org/patchwork/cover/599755) | 引入分区列表缓存(zonelist cache/zlc)是为了跳过最近已知已满的区域. 这避免了昂贵的操作, 如cpuset检查、水印计算和zone_reclaim. 今天的情况不同了, zlc的复杂性更难证明.
1. cpuset检查是no-ops, 除非一个cpuset是活动的, 而且通常是非常便宜的.
2. zone_reclaim在默认情况下是禁用的, 我怀疑这是zlc想要避免的成本的主要来源. 当启用该功能时, 它将成为节点满时导致暂停的主要原因, 并且让所有其他用户都承受开销是不明智的.
3. 对于高阶分配请求, 水印检查的计算代价是昂贵的. 本系列的后续补丁将减少水印检查的成本.
4. 最重要的问题是, 在当前的实现中, THP分配失败可能会导致order-0分配的区域被填满, 并导致回退到远程节点.
因此这个补丁尝试删除了 zlc, 这带来了诸多好处. | v1 ☑ 4.4-rc1 | [PatchWork v1](https://lore.kernel.org/patchwork/cover/599762), [关注 commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f77cf4e4cc9d40310a7224a1a67c733aeec78836) | | 2016/04/20 | Dave Hansen | [OOM detection rework](https://lwn.net/Articles/668126) | 只要还存在可回收的页框, 内核就有充分的理由不启动 OOM Killer. 因此 zone_reclaimable 允许多次重新扫描可回收列表, 并在页面被释放时进行重试. 但是问题在于, 由于多种原因, 我们并不知道内核需要花费多长的时间才可以完成对这些理论上"可回收"的内存页框的实际回收动作. 一种可以预见的情况是, 在回收单个页框时, 分配器会进入无休止的重试, 而那个回收的页框也无法被用于当前的分配请求. 最终的结果是分配尝试一直无法成功, 这导致了内核被挂起, 而且还无法触发 OOM 的处理. 这个补丁更改了 OOM 检测逻辑, 并将其从 shrink_zone() 中提取出来, shrink_zone 太底层, 不适合任何高层决策, 这个决策更适合放在 __alloc_pages_slowpath(), 因为它知道已经做了多少次尝试, 以及到目前为止的进展情况, 因此更适合实现这个逻辑. 新的启发式是在 __alloc_pages_slowpath() 中调用的 should_reclaim_retry() 实现的. 它试图更有确定性, 更容易遵循. 它建立在一个假设上, 即只有当当前可回收的内存+空闲页面允许当前分配请求成功(按照__zone_watermark_ok)时, 重试才有意义, 至少对于可用分区列表中的一个区域. | v6 ☑ 4.7-rc1 | [PatchWork v5,1/11](https://lore.kernel.org/patchwork/cover/664978)
*-*-*-*-*-*-*-*
[PatchWork v6,10/14](https://lore.kernel.org/patchwork/cover/670859))
*-*-*-*-*-*-*-*
[关注 commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0a0337e0d1d134465778a16f5cbea95086e8e9e0) | | 2016/06/13 | Minchan Kim | [mm: per-process reclaim](https://lore.kernel.org/patchwork/patch/688097) | 这个补丁允许用户空间主动回收进程的页面, 通过把手 "/proc/PID/reclaim" 有效地管理内存, 这样平台可以在任何时候回收任何进程. 一个有用的用例是避免在android中为了获得空闲内存而杀死进程, 这是非常糟糕的体验, 因为当我在享受游戏的同时切换电话后, 我失去了我所拥有的最好的游戏分数, 以及由于冷启动而导致的缓慢启动. 因为冷启动需要加载大量资源数据, 有些游戏需要 15~20 秒, 而成功启动只需要1~5秒. 通过使用新的管理策略来回收perproc, 我们可以大大减少冷启动(即. (171-72), 从而大大减少了应用启动. 该特性的另一个有用功能是方便切换, 这对于测试切换压力和工作负载很有用. | v2 ☑ 3.16-rc1 | [PatchWork](https://lore.kernel.org/patchwork/cover/688097) | @@ -1455,9 +1455,13 @@ Mel Gorman 观察到, 所有使用的内存页有三种情形: * RECLAIM_UNMAP +| 时间 | 作者 | 特性 | 描述 | 是否合入主线 | 链接 | +|:----:|:----:|:---:|:----:|:---------:|:----:| +| 2006/07/03 | Zhihui Zhang | [ZVC/zone_reclaim: Leave 1% of unmapped pagecache pages for file I/O](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9614634fe6a138fd8ae044950700d2af8d203f97) | 引入 min_unmapped_ratio, 控制只有 [NR_FILE_MAPPED 状态的文件页(所有基于文件的未映射页面, 包括 swapcache 页和 tmpfs 文件)所占的百分比](https://elixir.bootlin.com/linux/v2.6.18/source/mm/vmscan.c#L1604) 超过 min_unmapped_ratio 时, 内存域才会执行回收操作. 这样就在本地保留了一部分 page cache 等文件页面, 事实证明, 即使分区的所有页面(或几乎所有页面) 都已分配, 保留一小部分未映射的文件后置页面是有利的. 这允许最近使用的文件 I/O 缓冲区保留在节点上, 并缩短了在我们用完一个区域的内存时发生文件 I/O 时调用 zone_reclaim() 的时间. 当前默认设置 min_unmapped_ratio 为 1, 即保留约 1% 的文件页. | v1 ☑ 2.6.18-rc1 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9614634fe6a138fd8ae044950700d2af8d203f97) | +| 2009/06/16 | Mel Gorman | [vmscan: properly account for the number of page cache pages zone_reclaim() can reclaim](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=90afa5de6f3fa89a733861e843377302479fcf7e) | [Fix malloc() stall in zone_reclaim() and bring behaviour more in line with expectations V3](https://lore.kernel.org/patchwork/patch/159963) 的其中一个补丁, 这个补丁修改了 zone_reclaim () 计算给定当前 zone_reclaim_mode 下它可能回收多少页面的方式.
之前 min_unmapped_ratio 的检查条件中, 使用了 NR_FILE_PAGES 以及 NR_FILE_MAPPED 的所有页面, 这样是有问题的.
如果一个大的 tmpfs 挂载占用了很大百分比的内存, 这会造成 malloc() 会停顿很长时间(在某些情况下甚至是几分钟), 因为页面没有被 zone_reclaim() 清理或回收, 反而频繁地扫描列表, 使得 CPU 旋转接近 100%, 但却都是无用功.
引入 [zone_pagecache_reclaimable()](https://elixir.bootlin.com/linux/v2.6.31/source/mm/vmscan.c#L2373) 来根据不同的 zone_reclaim_mode 来计算可回收页面数目.
1. 如果 RECLAIM_SWAP 被设置, 将[考虑 NR_FILE_PAGES](https://elixir.bootlin.com/linux/v2.6.31/source/mm/vmscan.c#L2385) 作为潜在的候选页进行回收, 或者使用 `NR_{IN}ACTIVE}_PAGES - NR_FILE_MAPPE` 来折价 swapcache 和其他非文件支持的页面(non-file-backed).
2. 如果没有设置 RECLAIM_SWAP, 则[不会回收 NR_FILE_MAPPED](https://elixir.bootlin.com/linux/v2.6.31/source/mm/vmscan.c#L2387).
3. 如果没有设置 RECLAIM_WRITE, 则 [NR_FILE_DIRTY 页面不会](https://elixir.bootlin.com/linux/v2.6.31/source/mm/vmscan.c#L2391)被作为回收的候选页面. | v1 ☑ 2.6.31-rc1 | [PatchWork](https://lore.kernel.org/patchwork/cover/159963), [LKML](https://lkml.org/lkml/2009/6/11/143)
[关注 COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=90afa5de6f3fa89a733861e843377302479fcf7e) | +| 2015/06/24 | Zhihui Zhang | [mm: rename RECLAIM_SWAP to RECLAIM_UNMAP](https://lore.kernel.org/patchwork/patch/454625) | RECLAIM_SWAP 感觉上像是我们只处理匿名页面, 但是事实上, 最初引入 min_unmapped_ratio 的逻辑的补丁 [ZVC/zone_reclaim: Leave 1% of unmapped pagecache pages for file I/O](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9614634fe6a138fd8ae044950700d2af8d203f97) 是为了解决与文件页相关的问题, 将其重命名为 RECLAIM_UNMAP 更合适. | v1 ☑ 3.16-rc1 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=95bbc0c7210a7397fec1cd219f896ca95bf29e3e) | -| 2015/06/24 | Zhihui Zhang | [mm: rename RECLAIM_SWAP to RECLAIM_UNMAP](https://lore.kernel.org/patchwork/patch/454625) | NA | v2 ☑ 3.16-rc1 | [COMMIT](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=95bbc0c7210a7397fec1cd219f896ca95bf29e3e) | - +* RECLAIM_WRITE #### 4.1.1.4 node reclaim