PMFS文件系统
- 1. 背景(Background)
- 2. 动机(Motivation)
- 2.1 为什么设计NVM文件系统
- 2.2 NVM设备为文件系统设计带来的挑战
- 2.3 贡献
- 3. PMFS设计与实现(Design & Implementation)
- 3.1 系统概貌
- 3.2 Mmap I/O优化
- 3.3 一致性设计
- 3.3.1 In-Place更新
- 3.3.2 元数据一致性
- 3.3.3 页面分配器一致性
- 3.3.4 崩溃一致性(PMFS恢复)
- 3.3.5 数据一致性
- 3.4 写入保护
- 3.5 测试和验证
- 4. 评估(Evaluation)
- 4.1 实验设置
- 4.2 基于文件访问的测试
- 4.2.1 FIO
- 4.2.2 File Utilities
- 4.2.3 一致性性能测试
- 4.2.4 Filebench测试
- 4.3 Mmap I/O测试
- 4.3.1 FIO
- 4.3.2 Neo4j图数据库
- 4.4 写入保护测试
- 总结
- Features
拖了好久了,终于把这篇文章看了,假期还会读几篇文章,大家多多点赞、评论+关注,这样才有更新的动力呀!
1. 背景(Background)
NVM(Non-Volatile Memory)技术的诞生,进一步缓解了存储器与CPU速度不匹配的问题。并对如今软件、硬件的系统设计产生了极大的影响。
PMFS设计的目的便是通过洞悉NVM设备性能特性,设计高效的NVM文件系统,从而使得应用程序能够高效使用NVM设备。
NVM主要具有如下三个特性:
- 可字节寻址
- 存储持久化
- 低延时、高带宽
Table 1给出了当时的各存储设备特性,其中,NAND Flash是Flash设备,RRAM(Resistent-RAM,阻抗内存) 和PCM(Phase Change Memory,相变存储器) 是NVM设备。
注意:NVM的设备的延时和带宽在数量级上比较接近DRAM,但仍然差距1个数量级。
2. 动机(Motivation)
2.1 为什么设计NVM文件系统
传统的操作系统将易失内存管理(例:Virtual Memory Managment,VMM管理) 与存储设备管理(例:文件系统或块设备驱动) 分开。
NVM既具有内存的特性(可字节寻址),又具有存储设备的特性(可持久化)。因此,系统软件可依赖如下方式来管理NVM设备:
- 扩展VMM,用内存方法来管理NVM;
- 实现块设备兼容层,使得传统块设备文件系统(例如:EXT4文件系统)可以直接用于管理NVM;
- 针对NVM特性设计文件系统,绕过块设备层;
PMFS一文采用第三种方式,原因如下:
- 提供传统应用支持。大多数应用依赖于文件系统接口,故设计实现NVM文件系统;
- 提供更高效的文件系统。 PMFS绕过块设备层,充分利用NVM的字节访问特性来发挥NVM的性能;
- 提供优化的mmap I/O。 传统文件系统在
mmap
时,将页面拷贝到DRAM中,PMFS直接将NVM映射到用户空间,避免拷贝。
由以上种种原因,作者们决定设计针对NVM特性的文件系统。
2.2 NVM设备为文件系统设计带来的挑战
本节介绍PMFS设计的动机,通俗来讲:为什么PMFS要这么设计?
系统设计的动机非常重要,在任何工作中,动机一旦不成立,就没有做这个工作的必要了。
个人认为,动机也是一篇工作中最难的部分,它的好坏直接决定整个故事能否讲得圆满,能否逻辑闭环,因此,动机是整篇文章的灵魂。
动机常常伴随着一系列挑战,PMFS在文中提出如下挑战:
- NVM写入顺序和持久能力。PMFS将NVM视为一个具有回写缓存的内存。即,向NVM的写入不能保证持久性以及顺序性。为了解决这个问题,文章提出
pm_wbarrier
硬件原语用于保证写入的持久性。 - 有效避免恶意写入(Stray Write)。PMFS将NVM映射到内核空间,此时,并不能保证这段空间不会被其他BUG内核程序给污染(Corruption)。为了解决这个问题,有一种思路是将所有NVM页面标记为
read only
,然后写时将其变为writeable
,但这样会降低快表(TLB)的效率。于是,鉴于性能和简便性考虑,PMFS利用处理器的写保护控制手段,采用write windows
方法。 - 一致性验证方法。基于NVM的一致性验证方法较为复杂,PMFS采用YAT(该团队之前的工作)来进行验证。
- mmap接口还是过于底层。关于这一点,PMFS的设想是基于PMFS实现PMLib来封装
mmap
(可能类似于PMDK?),这一点留到以后去完成。
2.3 贡献
本文主要贡献如下:
- NVM系统新架构:
pm_wbarrier
硬件原语,用于保证NVM写入的持久; - PMFS文件系统的设计与实现:
- 细粒度一致性保证;
- mmap优化;
- 低开销避免恶意写入(Stray Write);
- 详细的性能评估
3. PMFS设计与实现(Design & Implementation)
3.1 系统概貌
- PMFS地位
PMFS向下管理NVM(文中称为Persistent Memory,PM)硬件设备,并向上应用层提供POSIX文件系统接口及直接NVM页面映射的mmap
方法。
PMLib将mmap
封装起来,以供应用更方便地访问。
- 文件系统布局
- Super Block
双Super Block冗余设计,降低系统崩溃后无法恢复风险。 - PMFS-Log
元数据项日志。 - 介质上索引
B-树结构组织访问,因为B树适合索引大量稀疏数据节点。
- 文件系统页面分配器
- 基于页面的分配器,支持4KB、2MB以及1GB页面。对于元数据,PMFS使用4KB页面;而对于文件数据,PMFS可以使用4KB、2MB以及1GB页面。
- 分配器的设计与操作系统虚拟内存分配器设计类似,但是提供了一致性和持久性保证。
- 该分配器仍然有碎片化问题,这留待以后去研究。
可以看到,整个PMFS的设计并不复杂,比较中规中矩。其较以往的文件系统的主要优势:与以往NVM文件系统(BPFS)相比,PMFS胜在细粒度元数据日志;与传统块设备文件系统(Ext 4)相比,PMFS胜在无需经过页面缓存(Page Caching)。
3.2 Mmap I/O优化
- PMFS将NVM上的数据直接映射到用户空间,于是用户可以直接访问NVM;
- PMFS的
mmap
将尽可能选择大页进行映射。利用大页进行映射的好处是:
- 减少Page Table内存占用开销;
- 更高效的TLS访问以及更少的Page Fault;
- 更短的Page Table Walk;
当然,这也有一定的弊端。比如,如果应用程序不需要大页映射,那么就会造成严重的内部碎片(例如:分配1G的内存页面,但是程序只用其中100MB,那么就有900MB的内部碎片)。为了优雅地解决这个问题,PMFS采用HINTS的思想——例如,如果一个程序想让文件增长到10GB,它便可以利用fallocate(10G)
或ftrucate(10G)
来告知PMFS,从而PMFS便选择用1GB的页面而非4KB的页面来表示一个文件数据。
3.3 一致性设计
最为核心的是细粒度日志设计。传统的保证一致性方法有三种:CoW(写时复制)、Jounaling(日志)、Log-structured(日志结构)。
考虑到CoW文件系统和Log-structure文件系统分别以Block或Segment粒度进行,这会带来不可忽视的写放大。而Jounaling机制又会带来Double Wirte问题,这不适于数据量大于4KB的写入。
综上考虑,PMFS采用Jounaling(和处理器自带的原子写操作)保护元数据一致性(通常是小数据),采用CoW保护数据一致性。(在NOVA一文中,作者说PMFS并没有保证数据的一致性,这里是否说错了呢?或者是PMFS的开源代码中还未实现CoW机制)。
3.3.1 In-Place更新
传统的NVM系统设计一般利用的是8字节原子写,PMFS根据硬件特性,采用了多种多样的原子写机制:
- 8字节原子写。处理器本就支持。
- 16字节原子写。利用
cmpxchg 16b
指令,加上LOCK
前缀。 - 64字节(Cacheline对齐)原子写。如果处理器支持Restricted Transcational Memory(RTM),那就可以,否则采用细粒度日志。
3.3.2 元数据一致性
- 日志结构: 利用一个循环Buffer作为日志,即PMFS-Log。日志包含
head
和tail
指针。 - 日志项: 每个日志项为64字节,如图4(b)所示。
- 事务动作:
- 开始事务: PMFS首先原子增长日志
tail
,在日志中写入所有即将被改变的元数据,最后,使用flush
和pm_wbarrier
保证这些写入成功持久化到NVM上。 - 结束事务: PMFS追加commit标记,并提交事务。这里要注意的是,commit标记不一定要使用
pm_wbarrier
。commit标记的持久化被延迟到下一次事务开始,或是被后台线程标记。
- 垃圾回收: 垃圾回收依靠后台线程
log_cleaner
执行,它会首先发送pm_wbarrier
,保证所有日志写入均已持久化,再原子地更新日志的head
指针以清除日志。
3.3.3 页面分配器一致性
PMFS将页面分配器布局在DRAM中,于是不必使用日志来保证它的一致性,从而降低了维护页面分配器一致性的开销。
在正常卸载时,PMFS将页面分配器存储在一个预留的Inode中,以便下次恢复快速构建页面分配器的状态。
3.3.4 崩溃一致性(PMFS恢复)
系统崩溃后,PMFS首先通过Undo PMFS-Log来完成系统一致性的恢复。其次,它扫描所有B-树来重建页面分配器。
3.3.5 数据一致性
通过CoW(写时复制)保证。数据的写入依靠NT Store
指令(Non-temporal Store)。
3.4 写入保护
PMFS详细地描述了对于NVM设备的写入保护方法,如表2(X-Y,即行-列,意味着避免Y影响X,原文是X from Y)所示:
其中,“用户-用户态”的写入保护依赖进程间隔离;“用户-内核态”的写入保护依赖Supervisor Mode Access Prevention(SMAP,管理模式访问保护)特性;“内核-用户态”的写入保护依赖特权级别。
“内核-内核态”的保护极具挑战性,PMFS认为使用write windows
方法(处理器的写入保护控制,CR0.WP)来实现写入保护:将整个NVM设备映射为只读,要写的时候开个写入窗口,写完后立马关闭窗口。如下图所示(其中,ring0代表Supervisor-mode,即内核模式或监督模式):
图5左上“CR0.WP in x86”代表内核写入逻辑:如果此时为内核态,且CR0.WP = 0,那么向页面P的写入是允许的,否则造成General Protection Fault。
需要额外注意的是,允许写入(disable_write_protection()
)过程是不允许中断的,从而保证此次写入只有当前调用disable_write_protection()
的PMFS在写。
3.5 测试和验证
文章通过Yat方法进行一致性检测与文件系统验证,并且设计fsck工具来进行完整性校验。最终得出结论:Yat适于检测基于NVM的系统的一致性。且表明PMFS的一致性经受住了考验。
4. 评估(Evaluation)
4.1 实验设置
- 实验平台: PM Emulator Platform(PMEP)
- PMDB: 为了保证实验的公平性,PMFS设计实现了PMBD,一个针对NVM优化的块设备驱动。传统的NVM块设备驱动不能区分NVM和DRAM,并且会受到操作系统分页机制的影响,而PMBD解决了这一问题,并且利用
NT Store
与pm_wbarrier
进行数据块的写入。
4.2 基于文件访问的测试
4.2.1 FIO
实验对象: PMFS、EXT4和EXT2(块设备文件系统代表)。这里并未与BPFS做对比,有点缺乏Convince。
实验设计: 单线程写入64GB文件,横坐标为I/O大小,纵坐标为带宽吞吐。
实验结果:
实验解释:
- PMFS在读写方面都更胜传统块设备文件系统(EXT4)一筹,主要得益于其避免了Page Caching的Double Copy;
- 可以看到,当写入的大小大于是16KB时,写入性能降低。这主要是因为
NT Store
指令。虽然NT Store
可以绕过CPU缓存,但还是需要检查CPU Cache来保证缓存一致性,从而引入额外开销。
4.2.2 File Utilities
实验对象: PMFS、EXT4和EXT2(块设备文件系统代表)。这里并未与BPFS做对比,有点缺乏Convince。
实验设计: 使用Linux Kernel Sources压缩包作为测试对象,并使用如下工具:
-
cp
:拷贝压缩包至相同目录下; -
untar
:解压压缩包; -
find
:在解压后的目录中找不存在的文件; -
grep
:在解压后的目录中找不存在的模式串; -
cp -r / rm -r
:拷贝整个解压后的目录 / 删除拷贝出来的目录;
实验结果:
实验解释:
不多提,PMFS在各种测试下都表现优异,特别是在写入较多(Write Intensive)的场景下,这在很大程度上是因为避免了Double Copy。但是在untar
过程中,PMFS提升不是很足,这是因为untar
仅涉及单线程顺序写,且对延时不敏感(对这个解释我不是很满意,根据4.2.1节中的分析,个人认为很大可能是untar涉及的I/O单元较小)
PMFS在rm -r
中效率低于EXT2,这是因为EXT2没有Journal操作,避免了额外的日志写入开销。
4.2.3 一致性性能测试
实验对象: PMFS、BPFS、EXT4
实验设计与结果:
- 首先,PMFS对In-Place原子更新与细粒度日志做了对比,发现In-Place原子更新性能更佳,提升大概为1.8X
- 其次,PMFS对细粒度日志做评估。BPFS采用CoW进行元数据保护,EXT4采用粗粒度日志(每个日志项4KB)对元数据进行保护,因此,PMFS需要额外引入的日志写入远远小于BPFS与EXT4
4.2.4 Filebench测试
实验对象: PMFS、EXT4、EXT2
实验设计: 使用Filebench对负载进行模拟
实验结果:
实验解释:
- 图8(a):图a是IOPS的对比,可以看到,PMFS在各种环境下性能都具优势。但是OLTP负载下提升较低,这是因为OLTP访问文件系统频率较低;
- 图8(b):对于OLTP这种访问频率较低的工作负载,增大NVM的延时使得PMFS性能基本不受到影响,而其他工作负载则不然;
- 图8(C):
pm_wbarrier
对性能的影响蛮大,因此需要合理使用;(这里很有意思的是,作者图纵坐标采用的是Normalized Performance,很有可能是持久化元数据影响并没有这么大,为了放大这种差距,才使用标准化指标。那么,为什么非要强调这一点呢?其实主要是为前面的事务commit设计做解释:为什么要减少pm_wbarrier
使用?是因为pm_wbarrier
会对性能造成巨大影响,如果这个影响不巨大,那么就没有减少的必要了……实际上个人认为多半是没必要的,因为元数据相比数据块而言实在太小,这些原语的延时基本会被数据块的写入隐藏,导致其对性能的影响微乎其微,当然,这是个人见解);
4.3 Mmap I/O测试
4.3.1 FIO
实验对象: PMFS、EXT4、EXT2
实验设计: 使用不同的页面大小,利用fallocate
创建文件进行测试。其中,PMFS-D
代表使用4KB页面;PMFS-P
代表使用4KB页面,并且在mmap
的时候使用MAP_POPULATE
选项,避免缺页影响;PMFS-L
代表使用1GB页面。
实验结果:
实验解释:
- PMFS的mmap直接将NVM页面映射到用户空间,避免了额外的拷贝,因此性能远远高于EXT4和EXT2;
- 大页
mmap
能够有效提升PMFS的mmap
性能; - 大页
mmap
能够有效缩短Page Table Walk的时间,减少Page Fault以及增大TLB命中率(图9 (c)),从而使得开销都只在用户态;
4.3.2 Neo4j图数据库
实验对象: PMFS、EXT4、EXT2
实验设计: 利用Wikipedia上的测试方法进行测试
实验结果:
实验解释:
- 插入性能与删除性能提升不太大,主要原因是基于PMFS mmap的Neo4j的插入与删除都是通过直接访问NVM完成的。这使得插入与删除性能主要受到NVM的写入影响;
- 读取性能提升非常大,主要是PMFS的mmap避免了拷贝,而是把NVM页直接映射到用户空间中;这也意味着未来的NVM软件设计都可以采用mmap读的方式;
4.4 写入保护测试
实验对象: PMFS采用PGT-WP(更新页表的权限)、CR0-WP(写窗口,即本文的方法)以及不要写保护;
实验设计: 利用FIO和Filebench进行测试;
实验结果:
实验解释:
- 可以看到,CR0-WP对于总体性能的影响微乎其微,适于写入保护;
- CR0-WP在Fileserver负载下一定的下降,这是因为对CR0.WP的修改是串行的,这对于多线程多写入负载场景会造成一定的性能下降。
- PGT-WP在写入较多的负载下性能会有巨大的下降(例如Fileserver);
总结
本文主要着眼于NVM带来的新型架构,并针对该架构进行大量一致性、持久化设计工作,以及性能优化工作。
我们回过头来看PMFS,其实主要优势在于:
- 绕过块设备层,直接访问NVM;
- 多样化原子写、细粒度日志以及CoW,保证系统一致性;
- mmap时,直接将NVM页面映射到用户空间以及隐式大页分配;
- 基于处理器CR0.WP的轻量级写入保护机制;
事实上,PMFS并没有在文件系统布局、索引或数据组织上下很大的功夫,主要为基于NVM的系统设计提供思想:NVM文件系统的本质是直接访问NVM、低一致性开销以及优化mmap。
这也难怪本文标题不是PMFS,而是”System Software for Persistent Memory“。
Features
- Redundent Super Block (Double Super Block).
- Various In-Place Atomic Update. 8Bytes, 16Bytes and even 64 Bytes.
- Fine-grained Logging. Comparing to CoW Journal, it brings low consistency overheads.
- OS VMM page allocator in DRAM.
- B-Tree In-NVM Indexing.
- Mmap directly within transparently large page (1 GB).
- Allocate page hints from syscall (
fallocate
andftruncate
). - Write window protection. Low overheads stray write protection by leveraging the processor’s ability.
- Validated by Yat.