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