一
通过fio工具测试磁盘性能
SPDK采用异步I/O(Asynchronous I/O)加轮询(Polling)的工作模式,通常与Kernel的异步I/O作为对比。在此,主要介绍通过使用fio评估Kernel异步I/O,以及spdk fio_plugin的两种模式。
01
fio评估kernel异步I/O(AIO)
fio支持多种模式的I/O引擎,同时也包含了测试异步I/O的引擎,即libaio。在测试异步I/O的时候,只需要将fio启动配置文件中的ioengine设为libaio即可。通常在做异步I/O的时候,I/O请求会发送到相应的队列中,等待被处理,因此队列深度将会影响磁盘性能。所以在测试异步I/O的时候,根据磁盘的特性指定相应的队列深度(iodepth)。
测试Kernel异步I/O的fio配置参数示例如下:
[Global]ioengine=libaiodirect=1rw=randrwrwmixread=100 (100% reads), 70 (70% reads 30% writes), 0 (100 writes)thread=1norandommap=1time_base=1runtime=300sramp_time=10sbs=4kiodepth=32Numjobs=1[test]filename=/dev/nvme0n1
参数详解
ioengine:指定I/O引擎,在这里测试Kernel的异步I/O,因此指定I/O引擎为libaio;direct: 指定direct模式O_DIRECT,I/O会绕过系统的page buffer;rw:读写模式,这里指定randrw表示混合随机读写;rwmixread:混合随机读写模式下read请求所占比例;thread:指定使用线程模式。由于spdk fio_plugin只支持线程模式,因此与Kernel对比时,通常都统一指定线程模式来对比;norandommap:指定I/O时,每次都获取一个新的随机offset,防止额外的CPU使用消耗;time_based:指定采用时间模式;runtime:测试时长;ramp_time:统计性能之前所运行的时间,为了防止没有进行稳态而造成的性能虚高带来的影响;bs:I/O块大小;iodepth:队列深度;numjobs:worker的个数;filename:指定测试的对象。
02
基于NVMe的fio_plugin
安装步骤
a. 下载编译fio:
git clone https://github.com/axboe/fiocd fio && git checkout fio-3.3make
b.下载编译SPDK:
git clone https://github.com/spdk/spdkcd spdk && git submodule update --init./configure --with-fio=/path/to/fio/repo
注意:由于fio_plugin要依赖fio中提供的一些依赖包,因此在运行configure时,必须指定fio目录,否则默认fio_plugin不会编译
测试方法
a. 使用fio_plugin测试裸盘,需要引入fio_plugin路径,因此在运行fio时,在fio命令之前加如下参数:
LD_PRELOAD=
b. 其次,需要在fio配置文件中设定ioengine为spdk。
c. 运行fio时候,不仅要指定fio运行配置文件,同时要通过额外的参数'--filename'指定spdk能够识别的设备地址信息。通常,fio_plugin支持两种模式下的测试,一是本地的NVMe设备,即NVMe over PCIe;二是远端的NVMe设备,即NVMe over Fabrics。如下所示:
NVMe over PCIe:LD_PRELOAD=.../fio_plugin fio config.fio '--filename=trtype=PCIe traddr=0000.06.00.0 ns=1'NVMe over Fabrics:LD_PRELOAD=.../fio_plugin fio config.fio '--filename=trtype=RDMA adrfam=IPv4 traddr=192.0.0.1 trsvcid=4420 ns=1'
其它说明
a. 对于使用1个core,测试多块盘的情况,通常只需要设定numjob为1,同时在fio命令通过多个filename参数来指定多块要测试的盘(多个filename参数之间用空格相隔即可),例如同时测试三块盘:
LD_PRELOAD=.../fio_plugin fio config.fio '--filename=trtype=PCIe traddr=0000.06.00.0 ns=1' '--filename=trtype=PCIe traddr=0000.07.00.0 ns=1' '--filename=trtype=PCIe traddr=0000.08.00.0 ns=1'
b. 对于使用fio_plugin作为新的ioengine而引入的新的fio参数说明,可以通过以下命令查看相关参数说明:
LD_PRELOAD.../fio_plugin fio --enghelp=spdk
c. 此外,可以通过直接在ioengine中指定fio_plugin的绝对路径,而无须每次运行fio都动态加载LD_PRELOAD。即: fio配置文件中添加修改ioengine=
03
基于bdev的fio_plugin
基于bdev的fio_plugin是将I/O在spdk块设备bdev之上进行发送。而基于裸盘的fio_plugin,I/O是直接到裸盘上进行处理。因此两者最大的差别在于I/O是否经过bdev这一层。因此,基于bdev的fio_plugin能够很好的评估spdk块设备层bdev的性能。
其编译安装与裸盘的fio_plugin完全相同,下面详细介绍其测试方法:
a. 使用fio_plugin测试bdev性能,需要bdev fio_plugin的路径,因此在运行fio时,在fio命令之前加如下参数:
LD_PRELOAD=
b. 其次,需要在fio配置文件中设定ioengine为spdk_bdev
c. 需要在fio配置文件中指定spdk启动配置文件。如下所示:
spdk_conf=./example/bdev/fio_plugin/bdev.conf
spdk运行配置文件中指定了所有bdev的配置信息,示例如下:
[Malloc]
NumberOfLuns 1 LunSizeInMB 128
[Nvme]
TransportID "trtype:PCIe traddr:0000:82:00.0" Nvme0
RetryCount 4 TimeoutUsec 0 AcctionOnTimeout None AdminPollRate 100000
d.运行fio的时候,通过'--filename'直接指定所要测试的bdev名称即可,示例如下:
LD_PRELOAD=.../fio_plugin fio config.fio '--filename=Nvme0n1'
其他说明
a. 使用基于bdev的fio_plugin测试多个设备时候,需要在spdk运行配置文件中写入相应的bdev配置信息,其次在fio运行时,指定多个filename参数即可,多个filename之间用空格相隔。例如同时测两个设备Malloc0与Nvme0n1,如下所示:
LD_PRELOAD=.../fio_plugin fio config.fio '--filename=Nvme0n1' '--filename=Malloc0'
b.同理,若查看基于bdev的fio_plugin相关参数说明,可以通过如下命令:
LD_PRELOAD.../fio_plugin fio --enghelp=spdk_bdev
c. 此外,可以通过直接在ioengine中指定fio_plugin的绝对路径,而无须每次运行fio都动态加载LD_PRELOAD。即:
fio配置文件中添加修改ioengine=
二
通过spdk perf测试磁盘性能
01
基于NVMe的perf工具
成功编译spdk后,可在spdk/examples/nvme/perf/目录下找到perf工具的二进制运行文件。perf使用方法如下所示:
perf -c
更多参数解析,请参考perf --help
perf支持本地的NVMe设备,同时也支持远端的NVMeoF的设备。使用范例如下:
NVMe over PCIe:perf -q 32 -s 1024 -w randwrite -t 1200 -c 0xF -o 4096 -r 'trtype:PCIe traddr:0000:06:00.0'NVMe over Fabrics:perf -q 32 -s 1024 -w randwrite -t 1200 -c 0xF -o 4096 -r 'trtype:RDMA adrfam:IPv4 traddr:192.0.0.1 trsvcid:4420'
对于同时测试多块盘,只需要添加-r并指定设备地址即可,例如一个core测试三块盘:
perf -q 32 -s 1024 -w randwrite -t 1200 -c 0x1 -o 4096 -r 'trtype:PCIe traddr:0000:06:00.0' -r 'trtype:PCIetraddr:0000:07:00.0' -r 'trtype:PCIe traddr:0000:08:00.0'
02
perf评估Linux异步I/O(AIO)
使用方式与测试spdkdriver相同,只需要在perf命令后添加设备名称即可。使用范例如下:
perf -q 32 -s 1024 -w randwrite -t 1200 -c 0xF -o 4096 /dev/nvme0n1
03
基于bdev的perf工具
成功编译spdk后,可在spdk/test/bdev/bdevperf/目录下找到bdevperf工具的二进制运行文件。bdevperf使用方法如下所示:
bdevperf -c
更多参数解析,请参考perf --help。
其中,-c是指定bdevperf的配置文件,需要测试的bdev设备都在配置文件中指定,例如,若需要测试本地的两块NVMe设备,则bdevperf的配置文
件示例如下:
[Nvme]
TransportID "trtype:PCIe traddr:0000:82:00.0" Nvme0 RetryCount 4 TimeoutUsec 0 AcctionOnTimeout None AdminPollRate 100000
相应的bdevperf启动参数示例如下:
bdevperf -q 32 -s 1024 -w randwrite -t 1200 -o 4096 -m 0xF -c bdevperf.conf
对于bdevperf,若要测试多块盘,则只需要在spdk配置文件中配置多块盘的信息即可,例如同时测试三块盘:
[Nvme]
TransportID "trtype:PCIe traddr:0000:82:00.0" Nvme0
TransportID "trtype:PCIe traddr:0000:83:00.0" Nvme1 TransportID "trtype:PCIe traddr:0000:84:00.0" Nvme2 RetryCount 4 TimeoutUsec 0 AcctionOnTimeout None AdminPollRate 100000
三
常见问题
1
通过fio与perf对SPDK进行性能评估,得到的结果不同,大部分的时候perf所得到的性能会比fio所得到的性能要高。
两种工具最大的差别在于,fio是通过与Linux fio工具进行集成,使其可以用fio_plugin引擎测试SPDK设备。而由于fio本身架构的问题,不能充分发挥SPDK的优势,整个应用框架仍然使用fio原本的架构。例如fio使用Linux的线程模型,在使用的时候,线程仍然被内核调度。而对于perf来说,是针对SPDK所设计的性能测试工具,因此在底层,不仅是I/O通过SPDK下发,同时一些底层应用框架都是为SPDK所设计的。例如刚刚所提到的线程模型,perf中是使用DPDK所提供的线程模型,通过使用CPU的亲和性将CPU核与线程捆绑,不再受内核调度,因此可以充分发挥SPDK下发I/O时的异步无锁化优势。这就是为什么perf所测得的性能要比fio高,尤其是在使用单个线程(单核)同时测试多块盘的情况下,fio所得性能要明显小于perf所得性能。因此,在同等情况下,我们更推荐用户使用perf工具对SPDK进行性能评估。
此外,在多numjob的情况下,fio与perf对iodepth的分配是不同的。通常在fio中,指定的iodepth表示所有的job一共的iodepth,而在perf指定的iodepth(perf中-q参数)通常指的是每个job所使用的iodepth。举例如下:Fio:numjob=4, iodepth=128。则每个job对应的iodepth为32(128/4)。Perf:-c 0xF (相当于fio中numjob=4),-q 128(相当于fio中iodepth=128)。则每个job对应的iodepth为128。
2
对SPDK和内核的性能评估时,虽然性能有所提升,但是没有看到SPDK官方所展示的特别大的性能差异。
首先,如问题1中所述,不同的工具之间所得出的性能结果是不同的,另外最主要的因素还是硬盘本身的性能瓶颈所导致的问题。例如,以2D NAND为介质的Intel DC P3700,本身的性能都存在一定的瓶颈,因此无论是SPDK用户态驱动还是内核驱动,都不会达到较高的IOPS。若换用更高性能的硬盘,例如使用以3D Xpoint为介质的Optane(Intel DC P4800X)为测试对象,便会看到很大的性能差异。因此,硬盘性能越高,SPDK所发挥出的优势越明显,这也是SPDK产生的初衷,其本身就是为高性能硬盘所订制的。
3
关于评估不同硬盘的队列深度(iodepth)与CPU core的问题。
通常根据不同硬盘的特点,选择不同的iodepth以及所使用的CPUcore。通常在评估以2D NAND、3D NAND介质的硬盘,一般情况下,为了达到磁盘的最高性能,通常会选择较高的iodepth(128或256)。对于P4XXX的硬盘,通常可能一个CPU core无法达到满IOPS,此时并不是由于一个core的能力不够,而是由于硬盘中硬件队列本身限制的问题。因此,通常需要使用两个CPU core才能够达到specification中的满IOPS。此外,对于以3D Xpoint为介质的Optane(Intel P4800X),通常只需要一个core并使用较小的iodepth即可达到满IOPS,此时已经达到硬盘的上限,若再次增大iodepth只会是latency变大而IOPS不再增长。
下面给出各种硬盘建议的评估参数:Intel P3700: numjob=1, iodepth=128Intel P4500、Intel P4510、Intel P4600:numjob=2, iodepth=256Intel Optane(Intel P4800X):numjob=1, iodepth=8/16/32
4
关于写性能虚高的问题。
通常以2D NAND、3D NAND为介质的硬盘,在测试write/randwrite的性能时候,通常要比sepcification里的最高值高很多。这是由于这类介质本身的问题,所以在测试时会出现write/randwrite性能虚高的问题。因此在测试该类硬盘,为了避免此类现象,通常需要对磁盘做一次precondition。通常的做法为:在格式化之后,对磁盘不断进行写操作,写满整个磁盘,使其进行稳态。以DC P3700 800GB为例,通常首先以4KB的大小顺序写两小时,之后再随机写一小时。此外,在测试的时候,fio参数中的ramp_time可以设置较大一些,避免初始的虚高值计入最终结果。
5
关于磁盘性能测试指标。
通常,对于一个磁盘的性能,我们主要从三方面去评估:IOPS、bandwidth、latency。
IOPS:通常评估磁盘的IOPS,主要关注块大小为4k,随机读写的情况。因此,通常fio关键参数为:bs=4k,iodepth=128,direct=1,rw=randread/randwrite。
Bandwidth:评估磁盘的bandwidth,通常是关注块大小为128k,顺序读写的情况。因此,通常fio关键参数为:bs=128k,iodepth=128,direct=1,rw=read/write。
Latency:评估latency通常情况下,是关注一个I/O发送/完成的延迟情况,因此,通常选择iodepth为1。因此,通常fio关键参数为:bs=4k,iodepth=1,direct=1,rw=randread/randwrite。此外,对于latency的结果,不仅要关注平均值,同时也要注意长尾延迟,即99.99%的延迟情况。
注意:通常在测试磁盘的性能时,要添加direct=1,即绕过系统的cache buffer。这时测得的性能为裸盘的性能 。
全部0条评论
快来发表一下你的评论吧 !