支持内存能耗管理的 VM Infrastructure

From: Ankita Garg
Date: Fri, 27 May 2011 18:01:28 +0530
http://lwn.net/Articles/445045/
翻译:王鑫

现代的系统为了满足应用程序的需要,在每一代都会提供更高性能的CPU以及更多的内存。内存子系统已经开始提供更为广泛的能力——电源能耗的管理,这就促使我们需要重新审视操作系统管理内存的方式。Linux VM 子系统如今使用复杂的算法来优化管理资源以求获得最好的整体系统性能:除了内存区域的容量和地址外, VM 子系统若有必要也会跟踪内存区段特定的受限的寻址,以及和CPU的相对距离而定义的不同NUMA节点。考虑到各类不同主存比如PCM、或者non-volatile RAM中的内存子系统的能耗管理能力,可以开发出 Linux VM 子系统新的边界能力和属性,从而进一步被内核和应用程序所利用。

本补丁集提供了一个可以被用来标记那些属于特定内存能耗管理领域的内存块的边界的通用memory regions架构,并且从长远来看,还能够在内存能耗管理功能平台上做进一步探索。

Linux VM如何帮助节省内存功耗的?

  • 合并内存分配的并且(或者)引用那些没有在整个内存空间被分散的。基本上,没有被引用的内存区域,可以处在低功耗状态。
  • 支持目标内存回收,对于那些特定部分的内存能够被轻易地释放,允许那些被置为低功耗态。

什么是Memory Region?

Memory regions是一个开启了虚拟内存管理的通用内存管理框架,它充分考虑了内存分配和回收时的内存特性。它是位于真正的NUMA节点之下的抽象出来的一层,并将下层的内存硬件信息封装于其中。这一层是在启动时就被创建的,并且含有相关平台可管理内存功耗粒度的固件中的信息。比如,在支持“部分数组自刷新”(PASR:Partial Array Self-Refresh)[1]的平台上,regions可以按内存单元对齐,而这可以使其独立地自刷新或者关闭(内容破坏关闭)。另一方面,支持多内存控制器的平台则是这样控制内存的功耗状态的——为单个内存控制器下的所有内存只创建一个memory region。

对齐的目的是为了确保内存的分配、重分配以及回收是在一个确定的硬件边界上执行的。通过在memory region中创建区段,伙伴分配器将会在区域级别上操作。提出的数据结构按下图所示:

Memory regions有以下功能:

  • 按照内存区域的顺序进行连续内存分配,因此保证了大号的内存区域总是比开头的那些内存区域缺少可分配的地址。
  • 然而随着时间的推移,分配的内存将会分散到不同的区域。但是区域边界的概念和区域级内存统计将会保证通过目标内存分配和回收来使得特定regions被释放。

Mel Gorman提出的块式回收以及其它内存压缩策略,将会更进一步合并内存[4]。

Memory regions只是一个最基础的架构,它将使Linux VM知道物理内存硬件的特性,同时它也是实现其它复杂算法和技术来真正节省功耗的根本。

进阶

Memory regions框架是同现有的内存管理数据结构一起工作的,并且只是添加了一个被要求捕获特定边界和属性信息的抽象层而已。大多数VM代码路径同当前的实现相似,只是额外多了以预定义顺序对区段数据结构的遍历而已。

其它方法:

当然也存在着一些把同属于同一功耗范围的内存分组的其他方法。在真实的NUMA节点下伪造NUMA节点可以把内存硬件单元的信息封装起来以进行独立的能耗管理。通过最少的代码改动却可以完成像memory regions一样的功能。然而,伪造NUMA节点并不是一个很直观的解决方法,它破坏了NUMA的语义并且事实上并不通用。通过展示比真实情况的更多的NUMA节点,它呈现给管理员的并非是系统的真实情况。

挑战

内存的交叉存取被广泛地用在所有平台上来增加内存的带宽,提升内存的性能。然而,交叉存取会降低硬件中闲置内存的数量,从而影响了节省能耗。对于一个给定的平台,选择一个即有好的性能又有最优的能耗节省的策略是十分重要的。

本邮件的附件是一个 Request For Comments 补丁集,用最少的功能代码演示了可以实现的选项。它已经在1Gb的RAM的TI OMAP4 Panda板子和Samsung Exynos 4210板子上测试过了。这个补丁在这两个平台下以默认的配置文件编译的,可以被应用在内核版本为2.6.39-rc5上。我关闭了cgroup,内存热插拔,和kexec。对于这些框架的支持可以很容易地被扩展。u-boot的引导程序还没有导出关于物理内存条的边界信息,因此regions并没有按照硬件正确对齐,当然只能以硬编码的方式来做测试和演示。而且,代码假定节点中至少有一个区域。memory regions的编译时间排除将是下一步要做的事情。

运行结果

在Samsung Exynos 4210板子上,2GB RAM,以4个memory regions启动,每个region 512 MB大小的环境下,运行pagetest——一个简单的分配和访问指定页面号的页面的简单的C程序。分配的大小是512MB。下面是运行这个基准程序时的空闲页的统计:

(区域3的总页面数是57332,由于它包含了剩下的所有页面,因此区域大小并不是512MB)。

第一列代表了每一个region在基准的起始处的空闲页的数目,第二列在480MB的地方分配的空闲页数目,第三列则是512MB。region 1、2和3的内存是空闲的,只region 0被使用了。因此如果region按照硬件内存单元对齐的话,空闲region则可以被潜在地置为低功耗状态或者关闭。当然也可以不用这种方式从低址分配,但是一旦页面回收开始运行,页面的分配将会分散开来。

参考文献:

[1] Partial Array Self Refresh
http://focus.ti.com/general/docs/wtbu/wtbudocumentcenter.tsp?templateId=...
[2] TI OMAP$ Panda board
http://pandaboard.org/node/224/#manual
[3] Memory Regions discussion at Ubuntu Development Summit, May 2011
https://wiki.linaro.org/Specs/KernelGeneralPerformanceO?action=AttachFil...
[4] Memory compaction
http://lwn.net/Articles/368869/

Topic: sohulinux