01 简介
本文发表于ASPLOS 23.
TLB容量的增长无法和内存足迹的增长相匹配。大部分情况下,使用4KB内存页时,TLB无法覆盖全部工作集。此外,当前的图处理应用通常使用指针访问下一个结点,空间局部性较差,预取的效果并不好。所以,这类应用的TLB miss开销达到20%~30%,甚至85%。
之所以TLB的容量增长受限,是其延迟、功耗的限制。L1 TLB的访问在L1 Cache的访问的关键路径上,所以它访问它必须非常快。因此它不能做太大。另一方面,TLB的能耗已经非常高(3-13%),如果为其设置更多的关联组或者更深的层次结构,势必会增加它的能耗。
增加TLB coverage的经典办法为使用大页,或者想办法聚集一些连续的页。然而,这些办法都仰仗于连续的物理内存。如果系统中没有足够多的连续物理内存,则必须执行去碎片操作。去碎片的开销往往超出大页带来的性能收益。例如,在没有碎片的服务器中,采用2MB页和4KB页相比,内存访问的带宽增加了29%;而在一个50%内存碎片的系统中,内存访问的带宽只有4KB页的89%。
为了降低碎片的影响,有一些工作提出增加复杂的硬件,把不连续的小页“缝”进大页中。例如Perforated Pages新增一个影子页表,将大页的部分区域重定向到4KB小页中,无需执行去碎片操作。这一方案的关键点在于,系统的性能提升依然源自大页内剩余的连续物理内存区域。相比于去碎片,填补空洞的效率总体上更高。
本文提出mosaic pages,旨在不使用连续的物理内存来提高TLB覆盖率。mosaic page基于哈希页表进行地址转换,大页不再需要连续的物理内存。为了展示这一设计的可行性,作者完成了从TLB到OS的端到端地址转换机制的实现。
具体来说,mosaic page使用Iceberg哈希来生成物理地址的哈希值、降低TLB冲突。
1.1 物理地址压缩(获取物理地址的哈希值)
mosaic page的关键设计思路为压缩物理页的地址,这样一个TLB项可以存放多个物理地址。如下图所示。
传统的映射机制下,一个虚拟地址对应任意p个物理地址;而通过物理地址压缩,一个虚拟地址只可以对应h个物理地址。这样一来,只需要logh个位来表示每个物理地址(过去需要logp个位)。物理地址压缩是通过哈希函数实现的。在现有的TLB架构中,可以实现a=logp/logh = 4,即在不带来任何负面影响,不需求连续物理内存的前提下,实现4倍的TLB覆盖率提升。通过扩展TLB entry的容量,可以令a=64。
1.2 哈希冲突的影响
在最坏的情况下,发生哈希冲突时所有h个位置都被热页占满。此时需要将一些热页丢弃或者swap到外存。当h增大后,哈希冲突的概率越低,越接近全映射的情况;当h变小后,单个TLB项可以存储更多物理页,TLB coverage会更大。本文的设计证明可以在不明显增大swap开销的前提下明显扩大TLB coverage。
1.3 Mosaic概览
作者把物理页划分为多个bucket,每个bucket含有多个slot,每个slot是一组连续的物理页。通过哈希函数,作者可以将VA对应的PA映射到d个bucket中的任意h个slot中。在本文的实现中,VA可以被映射到1个有56个slot的bucket和6个有8个slot的bucket,h=104,只需要7位来表示每个子页的物理地址。注意,Mosaic的实现并不需要哈希页表。只需要可以计算VA对应的哈希值即可。在操作系统中,页面依然可以采用radix tree管理。作者的原型使用了radix tree页表。
1.4 Mosaic的哈希算法
为了避免哈希冲突带来的页面迁移,Mosaic采用Iceberg哈希。具体的描述可以见后文。
02 设计理念
2.1 Mosaic Page的整体介绍
“Mosaic Page”就是虚拟上连续、物理上不一定连续的页。设a为Mosaic Page的子页(4KB)的数量,默认为4。Mosaic Page的子页甚至不一定全部在内存中。这样一来,繁复的物理碎片管理就被避免了。
如下图所示,Mosaic Page实现的方式是压缩物理地址。每个4KB子页都是独立分配的,但是会保证他们的物理地址会被限制在一定的范围内,以降低物理地址编码的长度。被这样限制过后的物理页框在本文中被称为”压缩物理页框(CPFN)“。TLB是通过mosaic page的虚拟页框(MVPN)来索引的,每个TLB项会含有一系列CPFN。一个mosaic page中的所有CPFN被称为它的”TOC“。
在地址转换时,通过mosaic offset确定CPFN的编号。取出特定的CPFN后,通过解码获取该4KB页的真实物理地址。Mosaic页表建立MVPN对多个CPFN的映射,可以和任何页表结构(如多级页、甚至软件TLB)兼容。
2.2 压缩物理页框(CPFN)
所谓的CPFN,就是当要为某个虚拟地址v分配物理页框时,只可能在h个可能的物理地址中分配。这样一来,物理页框号可以仅仅用 log(h)个位来表示。
作者把物理页框看作哈希表的 slot,它们被聚集为多个 bucket 。每个 VPN 通过哈希算法映射到1个或者多个 bucket中。CPFN表示分配器选择了哪个bucket以及 bucket中的哪个slot 。
用CPU缓存的术语来讲,传统的页表映射是全关联映射,而mosaic是组关联映射。
组关联映射的缺点就是可能产生哈希冲突。当发生哈希冲突后,一些本来不必被换出的页会被换出。可能导致即使物理内存足够充裕,也无法在内存中保留应用的全部工作集。
因此,为了优化、应用mosaic page的设计,需要解决两个重要的细节问题:
1)使用哪个哈希算法?
2)使用哪个页面替换算法?
2.3 哈希算法的选择
Mosaic选择Iceberg哈希算法,以保证较小的h、页面不会被迁移以及较高的内存利用率。
Iceberg哈希算法把所有的 slot(即物理页框)分为frontyard和backyard。frontyard被划分为s个大小为f的区域。backyard也被划分为s个大小为b的区域。 在本文中,f=56,b=8。
Iceberg的插入流程如下:
首先对于一个虚拟地址,执行 h0()将虚拟地址映射到某个frontyard的区域中。如果该区域内有空闲的 slot ,则插入成功(上图紫色);如果无空闲的 slot ,则依次执行 h1(),h2,()…,hd() 将虚拟地址映射到d个不同的backyard区域中,最终被放在最空闲的区域中(上图蓝绿色)。通过理论可以证明,Iceberg可以保证整体内存的使用率达到 1-σ。作者的实证证明, σ 约为2%。在本文中,d=6。所以h=56+8*6=104,CPFN的位数为7。
Mosaic的页面分配
Mosaic的页面分配算法将与哈希算法配合,如果成功插入,则分配对应区域内的某个空闲 slot 。
2.4 页面替换算法的选择
为了适配Mosaic,作者提出Horizon LRU替换算法。主要思路为剔除性能要求最低的目标bucket中的最不常用的页。
作者参考了组关联缓存的剔除策略,将组关联缓存看作比全关联缓存容量小的缓存,这样用户只能观察到缓存剔除,而不会观察到哈希冲突。
作者在此基础上进行了改进。首先,作者将要逐出的页面标记为幽灵页面。等到需要空闲空间时再真正逐出,以避免被二次换入的开销。其次,Horizon基于Mosaic的页面分配,维护局部LRU链表,而非全局LRU链表。然而,作者使用全局的时间戳水位线来标记幽灵页面,实现了全局LRU的效果。