随着存储技术的发展,对存储性能的不懈追求,高性能存储开始探索向内存通道的迁移。在这样的情况下, NVDIMM 技术便应运而生了。
NVDIMM (Non-Volatile Dual In-Line Memory Module) 是一种可以随机访问的,非易失性内存, 又被称作PMem (Persistent Memory)。在之前的微信文章中,我们介绍了NVDIMM几种硬件上的实现方式,以及为了支持和优化性能所做的硬件上的改变。今天,我们来讨论一下为了充分发挥NVDIMM的性能,软件方面做了哪些支持。有些人可能会有疑问, 为什么用起来这么麻烦?既然是持久性内存,不是应该关机什么样, 开机什么样, 就可以了吗? 其实目前来看, 这种想法还不会变为现实。 因为除了DRAM是易失性的,比如 cache,寄存器这种也是易失性的。仅仅把内存做成持久性的也不能达成这样的目的。另一个问题是, memory leak。如果发生了内存泄漏, 重启一下就好了。 那如果是持久性内存的泄漏呢?这也是一个很棘手的问题。Pmem有些方面类似于内存,也有些方面类似于存储。但是,通常上我们不会认为Pmem能够替代内存或存储。其实,可以把它看作是一种补充,填补了内存和存储之间巨大的差异。
SPDK 在 17.10 中开始引入对于Pmem的支持。Pmem在SPDK的bdev层暴露为一个块设备, 使用快设备接口和上层进行通信。如图(1)所示。
图(1)
从图中我们可以看到libpmemblk 把块操作转换成了字节操作。它是怎么做到的呢? 在介绍libpmemblk 和 它背后的PMDK之前, 我们了解一下基础知识。
mmap和DAX
首先,我们来看传统的I/O方式, 即缓存I/O (Buffered I/O). 大多数操作系统默认的IO操作方式都是缓存IO。该机制使IO数据缓存在操作系统的page cache 中, 也就是说, 数据会被先拷贝到操作系统的内核空间的缓冲区中,然后才会从内核空间的缓冲区拷贝到指定的用户地址空间。
图(2)
在Linux 中, 这种访问文件的方式就是通过read/write 系统调用来实现,如图(2)。接下来, 我们比较一下内存映射IO mmap().
接下来, 我们比较一下内存映射IO mmap().
图(3)
通过mmap获得了对应文件的一个指针,然后就像操作内存一样进行赋值或者做memcpy/strcpy. 这种我们称之为load/store操作(这种操作一般需要msync、fsync来落盘)。
mmap因为建立了文件到用户空间的映射关系, 可以看作是把文件直接拷贝到用户空间,减少了一次数据拷贝。但是, mmap依然需要依靠page cache。
图(4)
讲完了mmap, 那么DAX是什么呢?DAX即direct access,这个特性是基于mmap的。而DAX的区别在于完全不需要page cache. 直接对存储设备访问。 所以它就是为了NVDIMM而生的。应用对于mmap的文件操作, 是直接同步到NVDIMM上的。DAX目前在XFS, EXT4, Windows的 NTFS 上都已经支持。需要注意的是, 使用这个模式, 要对应用程序或者文件系统进行修改。
图(5)
NVM Programming Model
NVM Programming Model 大致定义了三种使用方式。
图(6)
最左边Management 主要是通过driver提供的API对NVDIMM进行管理, 比如查看容量信息, 健康状态, 固件版本, 固件升级, 模式配置等等。
中间, 作为存储快设备使用, 使用支持NVDIMM driver 的文件系统和内核, 应用程序不用做任何修改,通过标准文件接口访问NVDIMM。
第三种, 基于文件系统的DAX特性,通过load/store操作,不需要page cache, 同步落盘。没有系统调用, 没有中断。这也是NVM Programming Model 的核心, 能够充分释放NVDIMM的性能优势。但它的缺点在于,应用程序可能需要做一下改变。
PMDK
libpmemblk 实现了一个驻留在pmem中的同样大小的块的数组。里面每个块对于突然掉电,程序崩溃等情况依然保持原子事务性。libpmemblk是基于libpmem库的。
libpmem是PMDK中提供的一个更底层的库, 尤其是对于flush的支持。它能够追踪每次对pmem的store操作,并保证数据落盘为持久性数据。
除此以外, PMDK 还提供了其他编程库, 比如libpmemobj, libpmemlog, libvmmalloc 等。感兴趣的同学可以访问http://pmem.io/pmdk/ 获取更多信息。
SPDK实战
bdevperf测模拟NVDIMM性能
(1) 创建一个虚拟的Pmem bdev
./configure --with-pmdk
make
PMDK 已经在一些新的Linux发行版中被引入。如果configure出错,请到https://github.com/pmem/pmdk 自行安装PMDK库。
接下来, 我们可以通过SPDK RPC命令来建立一个pmem_pool。
rpc.py create_pmem_pool /path/to/pmem_pool
这里假设我们没有一个真正的NVDIMM做测试, 所以pmem_pool的路径就随便选择一个就好。比如:
rpc.py create_pmem_pool /mnt/pmem 128 4096
我们也可以用pmem_pool_info来获取创建pmem_pool的信息:
rpc.py pmem_pool_info /path/to/pmem_pool
或者,删除刚创建的pmem_pool:
rpc.py delete_pmem_pool /path/to/pmem_pool
然后, 我们在我们创建的pmem_pool上, 建立一个bdev块设备:
rpc.py construct_pmem_bdev /path/to/pmem_pool -n pmem_bdev_name
(2) 更新配置文件
更改/path/to/spdk/test/bdev/bdev.conf.in, 只保留Pmem配置的部分。
[Pmem]
Blk
Example:
[Pmem]
Blk /mnt/pmem-pool pmem-bdev
(3) bdevperf 测试
./bdevperf -c ../bdev.conf.in -q
Example command:
./bdevperf -c ../bdev.conf.in -q 128 -t 100 -w write -o 4096
./bdevperf -c ../bdev.conf.in -q 1 -t 100 -w randwrite -o 4096
结语
至此, 对于NVDIMM硬件和软件上的不同, 大家都有了一个大致的认识。Intel 在2018年5月发布了基于3D XPoint™ 技术的Intel® Optane™ DC Persistent Memory, 引发了NVDIMM爆点。如果你对NVDIMM的用法很感兴趣,或者对于NVDIMM的应用有好的想法, 欢迎通过私信或者在评论区评论交流。希望大家继续关注NVDIMM和SPDK技术。
全部0条评论
快来发表一下你的评论吧 !