原文链接

https://lwn.net/Articles/705758/

木名,十刀

VM子系统现在还有哪些问题? 基于这个话题,Mel Gorman(目前工作在suse的performance group,主要关注在提升小块内存分配性能提升上)、Rik van Riel(主要关注点在qemu里面通过使用persistent-memory技术将page cache从虚拟机里面移到宿主机上,便于管理和共享)、Johannes Weiner(主要工作是提升page-cache的抖动检测)、Vlastimil Babka(主要关注点是高order页的分配,Œ一方面是减少不必要的高order分配,virtually mapped kernel stacks 这套patch使得栈分配这块已经不再需要使用高order内存,另一方面是优化内存compaction和减少内存碎片)四位用了半个小时就此展开讨论,总结下主要在如下两个方面:

swap相关困扰

  1. 使用zram将内存swap到硬件设备时,其中有2/3的cpu消耗是在内存压缩,而另外1/3的cpu消耗是其他部分导致的,当内存压缩移植到硬件里面之后,另外的这1/3就是大头,需要定位清楚这部分消耗并做相关优化。

  2. swap对快速设备路径支持这块当前存在一系列问题(Johannes):

    • 换出路径的全局锁
    • vm子系统即使在page cache频繁被访问时也还是会倾向于回收page cache,而不是考虑进行swap
    • 换出路径对hugepage的拆分

Mel对这块总结是swap现在已经running into walls,需要重新思考下,这类问题大概需要6~24个月来进行fix。

诡异的shrinker

brtfs一位开发者做了一个实验,将系统80%的内存用来缓存inode和dentry,同时注册了shrinker保证这部分内存能够管理,结果观察到的现象是大部分时候都在扫描page cache,而当‰系统中并没有page cache,导致这些扫描都是无用的,同时注册的shrinker并没有被告知尽可能多的释放内存。ext4的开发者在extent status slab cache这块也碰到类似的问题,导致这个cache可能变得越来越大;同时在多个shrinker并发执行时还会有spinlock竞争问题。

Rik谈到VM子系统对此唯一能做的是调用相应的shrinker,但是对slab缓存,一个page可能包含很多个object,只有当这个page上面所有的object都free了†,对应这个page才能够被free,有可能大量的object被回收了,但是实际系统可用内存并没有增加多少。针对这个,有人提出需要有方式能够区分干净的object(能够立即回收的)和脏的object(需要先回写),同时需要有一个基于page的shrinker,能够快速找到所有object都是干净的page。

Mel建议需要增加一个帮助接口,给shrinker用来找到属于同一个page的所有object,这样可以一起释放。对于锁竞争,Œ一种方法是限制direct reclaim并发线程数,另外一种就是发现有人持锁时快速的回避(持锁者能够回收出相应的内存)。

还有一个问题,有一些object会将其他的pin在内存中,比如inode会pin对应的dentry,dentry会pin父目录的dentry。linus建议将叶子节点(类似普通文件)的dentry和目录的dentry分开来,叶子节点的dentry更容易被回收,因此将它们放到一块,这样可以增加释放整个page的概率。这样做唯一的问题是:内核在分配内存的时候并不能区分dentry的类型。Mel建议文件系统在发现放置错误之后重新再分配另外一个dentry,然后将数据拷贝过去。

最后Tim Chen介绍了下他的swap optimization work,由于persistent memory可以直接寻址,内核可以将换出的page直接映射到进程地址空间,避免重新swap回内存。但是这种方式如果对于页访问太频繁会有性能影响,因此需要有个机制能够评判什么时候需要swap回内存。对于普通内存有lru表,单对于persistent memory只有page table里面的access bit。到讨论最后这块目前还没有解决方案。