作者简介
惠春阳, Intel 软件工程师, 主要从事SPDK开发和存储软件性能优化的工作。
随着存储技术的发展,对存储性能的不懈追求,高性能存储开始探索向内存通道的迁移。在这样的情况下, NVDIMM 技术便应运而生了。
NVDIMM (Non-Volatile Dual In-Line Memory Module) 是一种可以随机访问的,非易失性内存, 又被称作PMem (Persistent Memory)。在之前的
SPDK 在 17.10 中开始引入对于Pmem的支持。Pmem在SPDK的bdev层暴露为一个块设备, 使用快设备接口和上层进行通信。如图(1)所示。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/4c61a97eb194d783779f52b751aff22b.jpeg)
图(1)
从图中我们可以看到libpmemblk 把块操作转换成了字节操作。它是怎么做到的呢? 在介绍libpmemblk 和 它背后的PMDK之前, 我们了解一下基础知识。
mmap和DAX
首先,我们来看传统的I/O方式, 即缓存I/O (Buffered I/O). 大多数操作系统默认的IO操作方式都是缓存IO。该机制使IO数据缓存在操作系统的page cache 中, 也就是说, 数据会被先拷贝到操作系统的内核空间的缓冲区中,然后才会从内核空间的缓冲区拷贝到指定的用户地址空间。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/ab17ae8aaea7ec9270a3e00ed08cba93.jpeg)
图(2)
在Linux 中, 这种访问文件的方式就是通过read/write 系统调用来实现,如图(2)。接下来, 我们比较一下内存映射IO mmap().
接下来, 我们比较一下内存映射IO mmap().
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/cef89362f5353cb79a6bfb056091de34.jpeg)
图(3)
通过mmap获得了对应文件的一个指针,然后就像操作内存一样进行赋值或者做memcpy/strcpy. 这种我们称之为load/store操作(这种操作一般需要msync、fsync来落盘)。
mmap因为建立了文件到用户空间的映射关系, 可以看作是把文件直接拷贝到用户空间,减少了一次数据拷贝。但是, mmap依然需要依靠page cache。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/de5272fe095b196a59b01add00b68fe8.jpeg)
图(4)
讲完了mmap, 那么DAX是什么呢?DAX即direct access,这个特性是基于mmap的。而DAX的区别在于完全不需要page cache. 直接对存储设备访问。 所以它就是为了NVDIMM而生的。应用对于mmap的文件操作, 是直接同步到NVDIMM上的。DAX目前在XFS, EXT4, Windows的 NTFS 上都已经支持。需要注意的是, 使用这个模式, 要对应用程序或者文件系统进行修改。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/79b7488dbc2eb317ae32373bb19fbcc4.jpeg)
图(5)
NVM Programming Model
NVM Programming Model 大致定义了三种使用方式。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/5c2728c6ea2b430945099b5f527d7bf0.jpeg)
图(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 <TotalSize (MB) > <BlockSize>
这里假设我们没有一个真正的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 <pmemblk pool file name> <bdev name>
Example:
[Pmem]
Blk /mnt/pmem-pool pmem-bdev
(3) bdevperf 测试
./bdevperf -c ../bdev.conf.in -q <iodepth> -t <time> -w <io pattern type: write|read|randwrite|randread>-o <io size in bytes>
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技术。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/4a4171ae0a86464cbb8d9abc0619644b.jpeg)
![640?wx_fmt=jpeg](https://i-blog.csdnimg.cn/blog_migrate/85e957be4b138cff7ecab36698155c77.jpeg)