linuxdebug/Documentation/translations/zh_CN/mm/balance.rst

82 lines
5.0 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/mm/balance.rst
:翻译:
司延腾 Yanteng Si <siyanteng@loongson.cn>
:校译:
========
内存平衡
========
2000年1月开始作者Kanoj Sarcar <kanoj@sgi.com>
对于 !__GFP_HIGH 和 !__GFP_KSWAPD_RECLAIM 以及非 __GFP_IO 的分配,需要进行
内存平衡。
调用者避免回收的第一个原因是调用者由于持有自旋锁或处于中断环境中而无法睡眠。第二个
原因可能是调用者愿意在不产生页面回收开销的情况下分配失败。这可能发生在有0阶回退
选项的机会主义高阶分配请求中。在这种情况下调用者可能也希望避免唤醒kswapd。
__GFP_IO分配请求是为了防止文件系统死锁。
在没有非睡眠分配请求的情况下,做平衡似乎是有害的。页面回收可以被懒散地启动,也就是
只有在需要的时候也就是区域的空闲内存为0而不是让它成为一个主动的过程。
也就是说内核应该尝试从直接映射池中满足对直接映射页的请求而不是回退到dma池中
这样就可以保持dma池为dma请求不管是不是原子的所填充。类似的争论也适用于高内存
和直接映射的页面。相反如果有很多空闲的dma页最好是通过从dma池中分配一个来满足
常规的内存请求,而不是产生常规区域平衡的开销。
在2.2中只有当空闲页总数低于总内存的1/64时才会启动内存平衡/页面回收。如果dma
和常规内存的比例合适即使dma区完全空了也很可能不会进行平衡。2.2已经在不同内存
大小的生产机器上运行即使有这个问题存在似乎也做得不错。在2.3中由于HIGHMEM的
存在,这个问题变得更加严重。
在2.3中,区域平衡可以用两种方式之一来完成:根据区域的大小(可能是低级区域的大小),
我们可以在初始化阶段决定在平衡任何区域时应该争取多少空闲页。好的方面是,在平衡的时
候,我们不需要看低级区的大小,坏的方面是,我们可能会因为忽略低级区可能较低的使用率
而做过于频繁的平衡。另外只要对分配程序稍作修改就有可能将memclass()宏简化为一
个简单的等式。
另一个可能的解决方案是,我们只在一个区 **和** 其所有低级区的空闲内存低于该区及其
低级区总内存的1/64时进行平衡。这就解决了2.2的平衡问题并尽可能地保持了与2.2行为
的接近。另外,平衡算法在各种架构上的工作方式也是一样的,这些架构有不同数量和类型的
内存区。如果我们想变得更花哨一点,我们可以在未来为不同区域的自由页面分配不同的权重。
请注意如果普通区的大小与dma区相比是巨大的那么在决定是否平衡普通区的时候考虑
空闲的dma页就变得不那么重要了。那么第一个解决方案就变得更有吸引力。
所附的补丁实现了第二个解决方案。它还 “修复”了两个问题首先在低内存条件下kswapd
被唤醒就像2.2中的非睡眠分配。第二HIGHMEM区也被平衡了以便给replace_with_highmem()
一个争取获得HIGHMEM页的机会同时确保HIGHMEM分配不会落回普通区。这也确保了HIGHMEM
页不会被泄露例如在一个HIGHMEM页在交换缓存中但没有被任何人使用的情况下
kswapd还需要知道它应该平衡哪些区。kswapd主要是在无法进行平衡的情况下需要的可能
是因为所有的分配请求都来自中断上下文而所有的进程上下文都在睡眠。对于2.3
kswapd并不真正需要平衡高内存区因为中断上下文并不请求高内存页。kswapd看zone
结构体中的zone_wake_kswapd字段来决定一个区是否需要平衡。
如果从进程内存和shm中偷取页面可以减轻该页面节点中任何区的内存压力而该区的内存压力
已经低于其水位,则会进行偷取。
watemark[WMARK_MIN/WMARK_LOW/WMARK_HIGH]/low_on_memory/zone_wake_kswapd
这些是每个区的字段,用于确定一个区何时需要平衡。当页面数低于水位[WMARK_MIN]时,
hysteric 的字段low_on_memory被设置。这个字段会一直被设置直到空闲页数变成水位
[WMARK_HIGH]。当low_on_memory被设置时页面分配请求将尝试释放该区域的一些页面如果
请求中设置了GFP_WAIT。与此相反的是决定唤醒kswapd以释放一些区的页。这个决定不是基于
hysteresis 的而是当空闲页的数量低于watermark[WMARK_LOW]时就会进行;在这种情况下,
zone_wake_kswapd也被设置。
我所听到的(超棒的)想法:
1. 动态经历应该影响平衡可以跟踪一个区的失败请求的数量并反馈到平衡方案中jalvo@mbay.net
2. 实现一个类似于replace_with_highmem()的replace_with_regular()以保留dma页面。
(lkd@tantalophile.demon.co.uk)