
Proactively reclaiming idle memory
By Jonathan Corbet
May 7, 2019
LSFMM
Shakeel Butt在2019 Linux Storage, Filesystem, and Memory-Management Summit会议中的主题演讲里,最开始先提醒了大家在data center(数据中心)的成本里,购买内存的成本其实占比非常大。因此数据中心运营方总是希望能对内存尽量利用充分,因此平时对客户承诺的内存其实很多情况下是overcommit的(承诺过高)。Butt介绍了Google是怎么改善内存的利用率的,听明白了之后,虽然大家都理解了确实需要增加他描述的这类功能,但是开发者们都不太喜欢他介绍的这种解决方案。
Overcommit内存,能够增加总的利用率,但是肯定会带来系统性能损耗:系统会经常碰到memory不够的问题从而导致经常需要回收页面(reclaim pages)。direct reclaim(就是指正在分配内存的进程需要直接做一些工作来把其他进程在用的内存给释放掉)通常会导致不少问题,因为它会引入一些此进程意料之外的delay,同时也会损害用户之间的隔离性。他认为对这类问题的解决方案就是能主动出击,在内存紧张之前就主动回收空闲页面。
最终实现里,数据中心的系统上搭载了各种慢速(更便宜)内存,包括各种类型的存储设备,例如persistent memory(非易失性存储),也可以利用内存压缩技术,或者直接用一个swap设备。系统对这些内存的管理方式对用户是透明的。空闲内存(专指一段时间没有人访问的页面)可以被定位出来,然后搬移到慢速内存设备上去。Butt指出在Google的数据中心里任一时刻平均有32%的内存被判别为空闲内存。在超出2分钟的idle等待时间之后内存就会被回收。然后其中仅有14%的页面会在后续因为有访问而重新加载回来,其他部分的页面的新主人使用的都很正常,没有受到打扰。
看到这里的话,大家可能在想为什么Google不用kernel已有的reclaim回收机制,就是kswapd kernel thread实现的这个功能。他说:“kswapd方案也能部分达到效果”,不过这是基于各种watermark设置(来保证某些百分比的内存空闲)而不是根据idleness(各个页面是否最近真的有人访问)。kswapd也会在多个NUMA nodes之间来平衡内存的使用率,不过对他要解决的目的来说没有什么帮助。另外,kswapd也是基于各种复杂的启发式规则的,他也不希望改变这部分。
所以,Google就开发了这套机制来跟踪一段时间没有访问的是哪些内存页面。目前已经实现好的方案有一个user-space进程会频繁读取sysfs提供的bitmap。不过这个方案CPU占用率偏高,并且内存浪费的也不少。所以目前在试一个新方案,基于一个名为kstaled的kernel thread。这个kernel thread会利用page里的flag来跟踪idle page,所以不会再浪费更多系统内存了,不过仍然需要挺多CPU时间的。还有一个新加的kreclaimd线程来扫描内存,回收那些空闲(没人读写访问)太久的页面。
CPU的开销并不小,会随着需要跟踪的内存空间大小,以及扫描的频率而线性增加。在一个512GB内存的系统上,可能会需要一个CPU完全用于做这部分工作。大多数的时间都是在遍历reverse-map列表来查找page mapping。他们试过把reverse-map的查找去掉,而是创建一个PMD page table链表,可以改善这部分开销。这样能减少CPU占用率到原来的2/7。还有另一个优化是把kreclaimd的扫描去掉而直接利用kstaled传入的一组页面,也有明显的效果。
Butt打算把这部分实现推送到Linux主线上去,毕竟这不是一个user space能处理的工作。Rik van Riel认为,虽然性能优化了很多,这个方案在应对大规模系统的时候还是会有问题。Johannes Weiner问Google为何要重新实现自己一套idle page tracking的机制,其实内存管理子系统里面意境有一个least-recently-used (LRU) list。其实跟LRU差不多,这套新机制也是在预测每个page今后被用到的可能性,他觉得新做的这套机制代价太高了。Butt回复指出Google觉得这个代价不是问题,而更希望避免让系统走入direct reclaim流程里去。
Weiner也指出Facebook也面临过同样的问题,所有的workload都需要放到container里去执行,用户需要明确申明需要使用多少内存,不过其实没人知道自己真的会用到多少内存,因此用户申请的内存数量都太多了,也就有了类似的overcommit和reclaim问题。Facebook的方案是采用pressure-stall information (https://lwn.net/Articles/759781/),根据这个来了解内存是否变得很紧张了,相应的会把LRU list里最久未用的page砍掉。假如这个举动导致更多的refault(指有人访问这些已经被换出的内存页面)发生频率,那么内存的回收就调整的不要太激进。这个方案能得到一个比较合理的结果,同时占用的CPU时间也会小得多。
讨论继续了一段时间,有一些共识:这类积极主动的内存回收会对很多用户都有帮助,但是目前这个方案的开销过大,基本不可能被合入Linux内核。
全文完
LWN文章遵循CC BY-SA 4.0许可协议。
极度欢迎将文章分享到朋友圈热烈欢迎转载以及基于现有协议上的修改再创作~
长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~