问题
在DRAM-PM异构架构中,文件系统为了充分发挥其性能,通常通过两类方法:使用DRAM作为PM的缓存(DRAM缓存)或提供对PM的直接访问(DAX)。
-
DRAM缓存,如VFS页面缓存,是传统文件系统(如EXT4和XFS[44])中的一种常见设计,用于弥补快速DRAM和慢速持久存储设备(如HDD和SSD)之间的性能差距。然而,许多研究[10]表明,在快速的全内存架构下,DRAM缓存会产生巨大的开销。
-
DAX,大多数现有系统(如NOVA[51]、SplitFS[20]和ctFS[31])都采用DAX,它绕过DRAM缓存,直接在PM上执行I/O。但仍有3个缺陷:
-
PM和DRAM之间的性能差距,PM延迟在数百到数千纳秒之间[18],远高于DRAM,PM延迟会限制文件系统的性能。
-
DAX会失去DRAM缓存提供的数据局部性。在高并发和强数据局部性的场景中,基于DAX的系统的性能不如DRAM缓存系统。
-
立即持久化是DAX的最佳场景,但在许多现实世界场景中,这是一种矫枉过正的做法[49]。
-
挑战
根据本文的定量分析,总结了在异构内存上构建高效缓存框架的两个挑战:
-
应用缓冲区和DRAM缓存之间的数据传输开销高。在应用程序和DRAM缓存之间传输数据是最关键的快速路径操作,但现有的缓存框架使用内存复制,会引入大量的性能开销。实验表明,在使用VFS页面缓存的文件系统中,数据复制占据了高达84%的开销。
-
缓存税。除数据传输之外,现有的缓存框架还花费大量精力在DRAM缓存和PM之间同步(刷新脏数据)和迁移数据(将数据移入/移出缓存)。目前,此类操作以同步和顺序的方式实施,并显著增加了性能损失(超过30%)。
以上问题的主要原因是,现有缓存框架(例如VFS页面缓存)是建立在虚拟内存子系统上的,很难避免缓存应用程序数据复制,或隐藏跨层数据同步/迁移的开销。
本文方法
本文提出了位于异构内存之上的缓存管理层,即FLAC,将DRAM缓存与操作系统的虚拟内存管理集成。FLAC提供异构内存的单层地址空间,通过利用FLAC上数据存储的公开接口,在数据I/O路径上享受高效的DRAM缓存。
-
零拷贝缓存。使用异构页表,将异构内存统一到一个级别。FLAC中的虚拟页面可以根据其状态(即缓存或驱逐)动态映射到DRAM或PM上的物理页面。设计了页面附加机制,是一组在异构页表上紧耦合的管理操作,以零拷贝的方式优化了应用程序和缓存之间的数据传输。页面附加的核心思想是通过强制写时复制(COW)在源地址和目标地址之间映射页面。FLAC分别通过滑动窗口缓冲区和批处理错误/分离来解决页面未对齐和昂贵的COW页面错误的副作用。零拷贝缓存使页面具有多个版本,它要求FLAC具有新的缓存管理机制,以确保数据一致性和高并发性。
-
并行优化缓存管理。利用零拷贝缓存带来的多版本,FLAC充分利用了数据同步和迁移与关键I/O路径的并行性。提出了两阶段刷新,允许脏数据同步中昂贵的持久性阶段无锁,并提出了异步缓存未命中处理,以分摊在后台将数据加载到缓存的开销。
进一步在FLAC上设计和实现了一个名为FlacFS的库文件系统。
微观基准测试表明,FlacFS在文件读/写方面比现有文件系统性能提高高达两个数量级。在实际应用中,FlacFS的性能分别比最先进的基于DAX和基于缓存的文件系统提高了10.6倍和9.9倍。
FLAC 设计
零拷贝缓存
异构页表
内核页表的自定义子级表(包括一个或多个PUD)。FLAC空间是一系列连续的内核虚拟内存地址,其大小等于可用的PM大小。FLAC空间中页面的位置(DRAM/PM)对于在其上运行的文件系统是透明的。当页面被缓存或删除时,页表中索引的地址会动态映射到DRAM或PM。属于FLAC空间的页表条目(PTE)在PM中复制以进行故障恢复。
PM分为三个区域。1) 持久PTE区域,记录虚拟地址和PM页面之间的映射信息。当页从DRAM刷新到PM时,FLAC会将PM设备中的相关偏移记录到持久PTE中以进行恢复。2) 日志区域,当调用持久数据修改API(pflush_commit/pfree)时,日志区域协作日志机制对FLAC级(如持久PTE)和FS级元数据(如索引节点)的修改。3) 页面区域,包含多个4KB的文件数据存储单元。在刷新过程中,数据页会保留在此区域。
页面附加进行数据传输
页面附加将源地址(from_addr)的页面映射到具有给定大小的目标地址(to_addr)。为了数据安全和隔离,在附加后将操作的页面设置为只读,这样页面的后续写入将透明地触发写时复制(COW)页面错误,确保应用程序内的内存操作不会影响已映射到全局缓存和其他应用程序的数据。页面附加过程中自动进行页面对齐,将地址扩展。
批次故障处理。应用程序直接在读/写缓冲区中处理数据时,会导致缓冲区中的大量页面出现COW故障。通过批量执行COW页面故障,减少TLB刷新次数,将数据从原始页面批量复制到新页面,只需要刷新TLB一次。
分离。在某些情况下,应用程序只想重用读/写缓冲区的空间而不是其数据,这是一种错误的共享情况(例如,预先分配日志缓冲区并在将其写入存储系统后重用)。为了避免COW页面故障,FLAC提供了分离API来将读/写缓冲区的地址重新映射到一些新的匿名页面,使后续对缓冲区的内存写入不会触发COW页面错误。
并行优化缓存管理
并行优化同步/迁移
现有的缓存框架执行缓存刷新和缓存未命中处理,需要大量的同步和迁移开销:缓存刷新会锁定脏页,直到它们被完全刷新,这会阻止前端写入并大大降低性能;缓存未命中会阻止I/O,直到页面加载到DRAM缓存。
两阶段刷新。将脏页刷新分为收集(pflush_add)和持久化(pflush-commit)。收集阶段将给定的脏页添加到刷新句柄中,为该句柄分配一个新的虚拟内存地址空间作为临时刷新缓冲区,将脏页附加到该缓冲区。此阶段需要锁定以防止并发写入修改目标页。持久化阶段将刷新句柄中的脏页持久化到PM,此阶段是无锁的。由于收集阶段的页面映射比跨层复制快得多,因此两阶段刷新机制显著减少了由于脏页面同步(例如后台刷新)导致的并发写入阻塞时间。
异步缓存未命中处理。缓存未命中对写入操作的影响较小,因为它不需要将页面加载到缓存中,但对读取操作影响很高。利用异构页表,FLAC可以直接将PM页附加到读取缓冲区(立即返回),并异步处理缓存未命中。FLAC的后台线程将未命中的页面加载到DRAM,并将指向这些PM页面的FLAC空间和应用程序缓冲区的PTE重新映射到缓存的DRAM页面。页面加载到DRAM之前可能已被修改以触发COW页面错误,因此在DRAM中具有最新版本。异步缓存未命中检查页面在DRAM中是否已有新版本,如果有,则跳过。
页面状态/版本转换
FLAC中的页面有四种状态:共享持久(SP)、共享缓存(SC)、匿名(AM)和过期(OD)。SP和SC页存储在全局区域(PM数据页区域/DRAM缓存)中,是只读的;AM页面可读写,与进程中的普通匿名页面相同;OD页面对FLAC上的文件系统不可见,由FLAC的回收机制管理。图5显示了页面状态/版本转换的示例。
页面状态语义。页面状态处于进程粒度。一个线程附加(通过文件读/写)具有SC/SP状态的页面后,同一进程中的其他线程可以一致地读取它。一旦修改了附加页面并导致COW生成AM页面,就可以在流程中共享。FLAC不支持不同进程之间的读/写共享页面(例如,将FLAC空间用作进程间共享内存)。FLAC强制隔离,不同进程中的COW将生成单独的AM页面。
持久性。在两种情况下,缓存的数据会持久化到PM:触发后台刷新和文件系统用户调用fsync。FlacFS通过封装FLAC的数据同步操作(pflush_add/commit)来实现后台刷新和fsync,FLAC保证这些操作是原子性的,并且可以通过FS-FLAC协作日志进行恢复。
缓存策略
FLAC空间的大小等于可用的PM大小,DRAM缓存的最大使用量是可控的,当缓存已满时会触发页面驱逐。这项工作只在原型中设计了一个简单的缓存策略,使用轮询方法选择要驱逐的页面。当满足两个条件时,才能删除页面:页面是干净的,即已经通过后台刷新或fsync同步到PM;页面的引用计数器为1,该页面不被任何应用程序使用。页面被驱逐到PM后,FLAC空间的目标PTE被重新映射到PM页面,DRAM页面将被回收。
FS-FLAC协作日志记录
对于正常终止,FLAC的恢复过程只需要根据持久PTE重建异构页表。对于意外终止,FLAC必须将系统恢复到上次一致的状态。为确保完全一致性,FLAC提供了FS-FLAC协作日志记录机制,允许在事务中对FLAC的数据进行修改和FS级元数据更新。它要求文件系统做两件事:1)当调用持久数据修改API时,文件系统应该提供自格式化的元数据日志(fs_metalog参数)。FLAC将内部(FLAC级别)和外部(FS级别)元数据日志连接到一个条目中,并在成功进行持久数据修改操作后将其附加到日志区域。2) 文件系统应使FLAC提供的外部元数据恢复功能过载。在恢复过程中,FLAC首先提交内部元数据日志,然后调用外部恢复函数提交外部元数据。提交所有日志后,FLAC可以恢复为正常关机。
实验
实验环境:两个Intel Xeon CPU,256GB RAM,1TB(128GB×8)PM。FlacFS和EXT4使用Ubuntu 20.04和Linux 5.1,其他文件系统使用它们可以支持的内核版本。
数据集:微基准测试、Filebench [45]、命令行应用程序 grep v3.7和tar v1.34、大数据处理 BigSort[25]
实验对比:执行时间、吞吐量、缓存逐出开销
实验参数:线程数、I/O大小、缓冲重写比例、文件大小
总结
针对异构内存的场景,现有的基于DRAM缓存(额外数据复制开销)和基于DAX的方法(数据同步和迁移开销)性能受限。本文提出FLAC,将DRAM缓存与操作系统的虚拟内存管理集成。包括两个技术:(1)零拷贝缓存。使用异构页表将异构内存统一到同一级别,根据页面状态(即缓存或驱逐)动态映射到DRAM或PM上的物理页面。设计了页面附加机制,通过强制写时复制(COW)在源地址和目标地址之间映射页面。(2)并行优化缓存管理。两阶段刷新,一阶段加锁将将脏页附加到缓冲区,二阶段无锁同步。异步缓存未命中处理,利用后台线程加载未命中页面。