HPC专题

《A High Performance File System

2019-10-07  本文已影响0人  CPinging

这是一篇Eurosys 16的清华文章,我将其做一个简单的总结工作

Introduction

由于:Given the anticipated high performance characteristics of
emerging NVMMs, recent research [6, 13, 18, 49] shows that the overheads from the generic block layer and copying data between the OS page cache and the NVMM storage significantly degrade the system performance.

文中讲到许多方案将通用IO层拿掉,以用来提升效率。

但是这样会由于NVM的读写不对称问题而导致性能下降。所以不得不对写操作进行buffer。好处有一下两点:

那怎么解决持久化问题呢(需要做trade off)?

问题反复提到了两次复制的问题。(将数据复制到DRAM的cache中;使用fsync将数据复制到存储中)

文章点明了目的:The goal of HiNFS is to hide the long write latency of NVM- M whenever possible but without incurring extra overheads, such as the double-copy or software stack overheads, there- by improving the system performance

即:降低NVM写延迟并且不带来额外的开销。

HiNFS使用DRAM做NVM的cache,并且使用memory的接口来代替速度慢的通用层。

上述情况为lazily,而对于eager-persistent file writes我们需要直接操作。但是这又引起了一致性的问题。所以需要系统能够检测到写的具体模式并作出相应的操作。

这里提到了HiNFS主要是针对文件IO进行的优化,而对MMap IO也有支持。

image.png

这个图中能够看出有一些应用是需要fsync的,而fsync的比例高说明

Memory mapped I/O就是把磁盘上的file映射到内存上,当我们从内存上fetch byte时,对应的file就被读取。同样的,当我们在内存上存储字节的时候,对应的file就被写入。这就让我们不需通过read和write系统调用而去操作I/O。mmap内存映射建立一段可以被多个进程读写的内存段。共享内存。

要坚信文档中说的,read和write是肯定有缓存的,这是内核为了提高硬盘效率必须做的优化。而为什么楼主测试的程序会看不出效果呢?原因其实你已经知道了,因为缓存是对内核而言,不是对程序而言的,所以内核存在一定的同步机制,不会让这种情况发生,具体是怎么同步的呢,大概是这样的,执行write之后,内核将数据缓存起来,等到缓存区满了之后或者执行了fsync再强制写入硬盘,这时候其实数据还不一定到了磁盘,因为硬盘也有一个缓存区,数据会首先写入那里。但是如果这是执行了read尝试读取刚刚写入的数据,内核会先判断这段数据在在缓存中有没有更新,如果有就会直接从缓存读取,所以就会产生一种假象,数据已经被写入硬盘,这其实是内核的一种策略。如果你想看数据是不是真的被写入硬盘,很简单,执行write之后,直接拔电源,重启后看看数据文件中数据是不是更新了。要强调一点,内核何时把数据写入硬盘是不确定的,所以即使拔电源也不一定会看到数据没有更新,但没有更新的概率会很大。

这里插入一些相关解释:

write

ssize_t write(int fd, const void *buf, size_t count);

将数据写到文件中. 注意, 如果文件是保存在硬盘中, write() 函数调用返回之后, 并不表示数据已经写入到硬盘中, 这时如果掉电, 数据可能会丢失.

fsync

int fsync(int fd);

程序调用本函数, 通知内核把数据写到硬盘(file)中. 比如, 你开发一个数据库软件, 就需要这样的函数, 否则掉电或者系统崩溃时便会丢失数据.

如果你的程序不调用 fsync(), Linux 内核也会自动在”合适”的时候将你的数据真正写入到硬盘(类似调用 fsync), 最长的延时默认是 30 秒.

这里有一个小疑问:

simply using DRAM as a cache of NVMM may improve the performance for workloads having many lazy-persistent writes, but this simple design will significantly degrade the system performance for workloads containing many eager- persistent writes due to the double-copy overheads

为什么这里说到用DRAM做cache是可以提高那些lazy-persistent密集型应用,但是对于eager- persistent 应用却不太好。

我认为是不是这样:eager类型的写本来就需要实时性,所以将其先保存到DRAM中还是要立刻刷到NVMM中,所以是多此一举的。而利用Buffer的概念是为了有个时间差,但是这种模式不需要时间差,所以不合适。

HiNFS设计

image.png

上面的模式为传统的模式,需要两次复制(块设备与OS page;PS page与user的buffer)。这个花销太大。

image.png

上图为NVM-aware的文件系统,该系统仅需要一次用户buffer到NVMM的复制。

但是这个没有考虑NVMM的写问题。所以提出了第三种设想:

image.png

NVMM-aware Write Buffer Policy To

image.png

先判断是不是lazy,如果是直接放到DRAM的buffer中。用以进行IO整合工作以便提高性能。

image.png

上图为DRAM Block Index in HiNFS。

树的索引中,key表示了DRAM中块的逻辑文件偏移量;而value表示DRAM物理块号对应的NVMM中的物理块号。并可以后台将DRAM块刷到对应的NVMM块地址中。

为了保证数据一致性,HiNFS使用了多线程将DRAM中的块刷到NVMM中。并且有两个唤醒条件。

而这里需要注意的是:传统buffer管理方案使用的粗粒度的,而这里需要用细粒度的。

这里仍然存在两个问题:

为了解决问题,这里提出了Cacheline Level Fetch/Writeback (CLFW)

用其来追踪DRAM块中的cacheline的状态。当DRAM中的块数据需要转移到NVMM的时候,那么我们需要检查该其标志是否为1 。

这里放一个cache line的解释:https://blog.csdn.net/qq_21125183/article/details/80590934

文中提到了一个fetch-before-write不是很懂??

Elimination of the Double-Copy Overheads

文中说道其发现了两个造成double-write的原因。

读是非常简单的,应为dram与nvm读速度相当,所以可以直接读取即可。

然而,在读的过程中为了找到最新的数据,首先查找DRAM Block Index是在dram还是在nvmm。

在nvmm中直接读,在dram中在去找Cacheline Bitmap。

上面是读操作,下面是eager写操作。

直接写到nvmm中即可。

所以设计了Buffer Benefit
Model,来检测是否有足够的异步写。使用了最近的系统异步写历史信息来帮助我们进行判断。并且每4kb数据设置了一个Eager-Persistent位,来判断写入的类型。

文中也具体引入了一个公式来对该表标记位进行设置。

开始的数据均标记为lazy,并在之后动态调整。

为了预测下一个到来的写操作是什么类型的,本文引入了一个公式来预测。结果如下:

image.png

效果很棒。
These results demonstrate that the synchronization information of a block remains nearly the same within a short time period

为了保证NVM与DRAM中的数据一致性,如果为同步写情况,那么我们进一步检查buffer是否在DRAM中;如果在NVM中直接写入。

上一篇下一篇

猜你喜欢

热点阅读