当前位置:首页 期刊杂志

一种高效的持久性内存管理系统设计

时间:2024-05-04

余海涛

摘   要:近年来,研究者针对持久性内存的管理做了许多工作,但仍存在一些问题,比如未考虑数据一致性、读写不对称和非均匀存储器存取特性。文章提出了一种高效的持久性内存管理系统,设计了基于内存缓存的一致性策略,和基于非均匀存储器存取特性的多粒度内存管理策略。测试结果表明,在多线程下,分配内存大小为64字节时,相比于Makalu,持久性内存管理系统的平均性能提高了38.6%。

关键词:持久性内存;一致性;可扩展性

近年来,持久性内存得到了快速地发展,具有非易失性、字节寻址和读写性能,与将动态随机存取存储器(Dynamic Random Access Memory,DRAM)有相似的优势,但是也存在读写性能不对称、耐久度较弱等缺陷。本文针对以上问题,提出了一种高效的持久性内存管理系统(Persistent Memory Management System,PMMS),设计了基于内存缓存的一致性策略,通过DRAM作为缓存,缩短持久化的路径,减少一致性开销;设计了基于非均匀存储器存取(Non-Uniform Memory Access,NUMA)特性的多粒度分配与释放策略,通过将NUMA特性与多粒度内存操作相结合,保证了系统在多线程下内存分配与释放的高效性;设计了基于写入时间间隔和阈值相结合的磨损均衡策略,通过预先设定持久性内存块的时间间隔和阈值,来保障持久性内存块的磨损均衡。

1    持久性内存管理系统结构设计

根据PMMS的特性,本系统结构可分为三大模块:内存一致性管理模块、分配与释放管理模块和磨损均衡管理模块,该系统结构如图1所示。

1.1  内存一致性管理模块

CPU的乱序执行指令会造成数据写入持久性内存的不一致性问题,因此,需要显示同步执行的缓存刷写指令,将数据从高速缓存刷写至持久性内存。一方面,此类指令开销高昂,严重影响了CPU的执行效率;另一方面,持久性内存的读写性能相比于DRAM较弱,直接将数据写至持久性内存会造成严重的读写延迟。因此,本文设计了基于内存缓存的一致性策略,使用DRAM作为持久性内存的缓存,将数据和日志先写入DRAM,然后通过后台线程异步写入持久性内存,来保证系统的一致性。针对每一次操作,本系统首先将其记录至日志,日志内容为操作的类型、地址和内存大小,然后将日志使用后台线程异步写回至持久性內存,不会影响本系统主线程的分配与释放性能,最后将数据以同样的方式写至持久性内存。

1.2  分配与释放管理模块

内存的分配与释放作为底层基础操作,对上层应用的性能有着关键的影响。首先,需要保障内存分配与释放的速度。其次,现在计算机大部分具有多个CPU,它们之间的访问存在延迟不均的情况,不考虑这种特性将会影响内存分配与释放的性能。为此,本文设计了基于NUMA特性的多粒度分配与释放策略。

本文利用系统函数申请8 GB的虚拟地址空间,由于虚拟地址只有在真正被使用的时候才会映射到对应的物理地址,所以在64位的操作系统中不必担心地址空间不足的问题。本系统将申请的内存对象分为3个粒度,分别是小粒度(小于4 KB)、中等粒度(4 KB到2 MB)和大粒度(大于2 MB);定义多粒度内存管理单元,分别有page(4 KB),chunk(128 KB)和block(4 MB)。针对小粒度对象,本系统将其划分为不同的级别,用数组保存级别,例如,8字节、16字节、32字节等,当收到待分配请求时,本系统首先计算该申请对象的内存粒度,然后再计算其大小级别。若为小粒度对象,则从DRAM小粒度对象级别的双向链表中分配一个条目。针对中等粒度对象,本系统分配多个chunk的方式满足其分配请求。针对大粒度对象,本系统使用操作系统大页的方式处理。在虚拟内存管理中,虚拟地址到物理地址的映射转换过程由内核管理,对于每一个页面的转换,内核需要查询对应的映射表,系统页面默认大小为4 KB,当申请的内存块较大时,内核需要查询更多的映射表,这样会占用更多的内存,降低系统的性能。所以,针对大粒度对象的分配操作,使用系统的大页处理,尽可能降低系统的页面载入和查询开销,提高分配大内存块的速度。设置大页为2 MB,使用madvise函数的方式向内核申请以大页的方式映射内存,当申请的内存对象大于2 MB时,使用2 MB对齐分配,充分利用虚拟地址延迟映射物理内存的机制。分配操作步骤为:首先获取DRAM中空闲块地址,然后将该分配信息写入日志,最后将地址返回给应用程序。释放操作的步骤为:首先读取该释放块的头文件,然后获取释放块的大小,最后将该块添加至DRAM对应的双向链表。

针对NUMA特性,本系统设计了线程绑核策略,将线程绑定至CPU核心,使得线程优先分配本地核心所在的内存,如果不能满足请求则分配远端内存。针对多线程之间的扩展性,本文设计了线程本地存储策略,使用Hoard[1]中相似的思想,将持久性内存分为全局堆和线程堆,线程堆内的分配与释放操作不需要加锁,这减少了线程间的资源竞争开销。

1.3  磨损均衡管理模块

相比于DRAM,磨损均衡管理模块持久性内存的耐久性较弱,因此,需要均衡的写入持久性内存。本系统设计了基于写入时间间隔和阈值相结合的磨损均衡策略,需要预先设置持久性内存块以及两次被写入的时间间隔和阈值,记录不同粒度的内存块记录写入的时间戳和写入次数。当达到时间间隔时,该内存块才能被再次分配,分配时需要按照该内存块磨损值排序,然后分配磨损值最小的内存块。这样可以在满足分配要求的同时,均衡地分配持久性内存。

本系统在实现过程中采用了优化性能的技巧:有指令预取和日志压缩。通过使用__builtin_expect指令使得CPU可以预取下一条指令,减少CPU等待取指令的耗时,提高CPU的效率。通过使用lz4[2]压缩算法将日志压缩后写入持久性内存,减少对持久性内存的磨损。

2    实验测试与分析

为了分析持久性内存管理系统PMMS的性能,本节将从两个方面对PMMS进行测试与分析:(1)不同分配内存大小下的性能对比测试。(2)在多线程下的性能对比测试。

2.1  测试环境

本系统所有实验均为相同的服务器环境,服务器配置环境如表1所示,操作系统为Centos 6.8,内存为64 GB,由于目前持久性内存尚不可用,本系统使用8 GB大小的DRAM模拟持久性内存,使用RDTSC指令模拟延迟,默认情况下,将延迟设置为200 ns,实验对比对象为持久性内存分配器Makalu和Glibc默认分配器ptmalloc。

2.2  不同分配内存大小下的性能对比测试

上层应用的分配请求主要集中在小内存块的分配,本节测试各分配器分配内存大小为64字节到1 024字節下的性能,单线程分配次数为20 000次,实验结果如图2所示。

从图2中可得,分配内存大小为64字节到1 024字节时,PMMS的分配时间均少于Makalu,分配内存大小为1 024字节时,相比Makalu,PMMS的分配时间减少65%,主要是因为PMMS将DRAM作为持久性内存的缓存和设计了多粒度的分配策略,减少了分配操作的延迟。分配内存大小为64字节到256字节时,ptmalloc的分配时间最少,主要是因为它针对256字节以下的内存分配设计了快速分配的数据结构,分配内存大小高于256字节时,ptmalloc的性能不如PMMS。

2.3  在多线程下的性能对比测试

本节测试各分配器在多线程下的性能,分配内存大小为64字节和64~512字节之间的随机值,实验结果如图3—4所示。

从图3—4可得,在多线程下,PMMS每线程每秒的分配次数要优于Makalu,分配内存大小为64字节时,相比于Makalu,PMMS的平均性能提高了38.6%。主要是因为PMMS设计了基于NUMA特性的多粒度分配与释放策略和线程本地存储策略,减少了线程间的资源竞争,提高了CPU的处理效率。在64~512字节之间,分配随机值时,PMMS的性能略优于ptmalloc,主要是因为针对小粒度内存设计了多级别更细粒度的管理,充分利用了DRAM作为缓存的优势。

3    结语

持久性内存的出现给计算机系统设计提出了新的挑战。比如,持久性内存的一致性和传统的分配器未考虑持久性内存的读写不对称和耐久性较弱等问题。为了解决这些问题,本文设计了一种持久性内存管理系统PMMS,实验结果表明,单线程下,分配内存大小为1 024字节时,相比于Makalu,PMMS的分配时间减少了65%;多线程下,分配内存大小为64字节时,相比于Makalu,PMMS的平均性能提高了38.6%。

[参考文献]

[1]BERGER E D,MCKINLEY K S,BLUMOFE R D,et al.Hoard:a scalable memory allocator for multithreaded applications[C].Cambridge:ASPLOS-IX Proceedings of the 9th International Conference on Architectural Support for Programming Languages and Operating Systems,2000.

[2]NAMELESS.Extremely fast compression algorithm[EB/OL].(2019-02-10)[2019-10-25].https://github.com/lz4/lz4.

免责声明

我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自各大过期杂志,内容仅供学习参考,不准确地方联系删除处理!