SPDK生态工具(二):性能评估工具

在之前的《SPDK生态工具(一):监控管理工具》一文中,我们详细介绍了SPDK监控管理工具,今天带来的这篇文章将向大家介绍:SPDK生态工具之性能评估工具。

fio_plugin

通常,在内核模式下,使用fio工具来测试设备在实际的工作负载下所能承受的最大压力。用户可以启动多个线程,对设备来模拟各种IO操作,使用filename指定所被测试的设备。然而,在SPDK用户态模式情况下,SPDK在使用前会unbind内核驱动,直接通过PCI地址来识别设备,因此用户在系统上无法直接看到设备。为此,SPDK推出fio_plugin与SPDK深度集成,用户可以通过指定设备的PCI地址,来决定所要进行压力测试的设备。同时,在fio_plugin内部,采用SPDK用户态设备驱动所提供的轮询和异步的方式进行I/O操作,I/O通过SPDK直接写入磁盘。

SPDK提供两种形态的fio_plugin:

  • 基于裸盘fio_plugin,其特点为I/O通过SPDK直接访问裸盘,常用于评估SPDK用户态驱动在裸盘上的性能。
  • 基于bdev的fio_plugin,其特点为I/O测试基于SPDK块设备bdev之上,所有I/O经由块设备层bdev,再传送至裸盘设备。常用于评估SPDK块设备bdev的性能。

在编译时,fio_plugin要依赖于一些原本fio所提供的库文件,因此在编译SPDK前,要首先编译fio,并且在运行SPDK configure脚本时,要指定fio源码的路径,否则fio_plugin默认是不会编译的。例如

下面我们来介绍fio_plugin的使用方法。

1. 基于裸盘的fio_plugin

在使用fio_plugin的时候,基本的命令与参数和fio的相同。只有以下两点需要变化:

(1)在测试SPDK性能的时候,fio的配置文件里ioengine设为spdk。如果要测试内核驱动的性能作为对比,ioengine要使用Linux所提供的异步I/O,此时ioengine应设为libaio。使用spdk引擎测试,配置参数示例如下:

(2)指定测试设备需要在fio_plugin启动时,通过命令行参数–filename来指定。即

fio_plugin提供了两种模式的设备类型,如下:

a. NVMe over PCIe :测试的时候,指定PCI地址,以及namespace,例如:

b. NVMe over Fabrics:测试的时候,指定IP地址、类型以及namespace,例如:

2. 基于bdev的fio_plugin

在使用基于bdev的fio_plugin时,SPDK会通过配置文件,在特定的设备上初始化bdev。因此启动时,需要指定SPDK应用程序配置文件(与SPDK NVMe-oF、SPDK vhost启动时候所指定的配置文件基本相同),同时在测试时,测试设备应设定为相应的bdev名称。所以,与fio相比,在使用上的差别可以总结为以下两点:

(1)在测试SPDK性能的时候,fio的配置文件里ioengine设为spdk。同时,要添加SPDK启动配置文件路径spdk_conf。
(2)指定测试的块设备需要在fio_plugin启动时,通过命令行参数–filename来指定。

注意事项:

1. fio_plugin限制只能使用线程模式,因此在fio配置参数中,需要制定thread = 1。
2. 当测试random模式的read/write时候,因为在random map的时候,要额外耗费很多的CPU cycle,从而降低性能。因此在测试randread/randwrite的时候,建议指定norandommap=1。

perf

SPDK提供自己的性能测试工具perf。SPDK的perf与通常Linux系统中的perf工具有所不同,SPDK中的perf主要是用于对设备做压力测试,来评估其性能的工具。perf相比于fio_plugin更加灵活,可以直接配置core mask来指定进行I/O操作的CPU核。SPDK通过使用CPU的亲和性,将线程和CPU核做绑定,每个线程对应一个CPU核。在启动perf时,可以通过core mask指定所用的CPU核,在所指定的每个CPU核上,都会为之注册一个worker_thread进行I/O操作。每个worker_thread都会调用SPDK所提供的I/O操作接口,通过异步的方式向底层的裸盘发送读写命令。
perf的使用方法如下所示:

下面给出一个perf的使用范例:

在这里,core mask为0xF,代表我们使用核1,2,3,4来创建4个worker_thread对PCI地址为0000:06:00.0的盘进行随机写操作,其中-q 表示queue depth, -s 代表block size, -t 代表time。

相比于fio_plugin,perf有以下优势:
1. 可以通过core mask灵活指定CPU核。
2. 如果使用单个线程来测试多块盘性能的时候,fio_plugin的所得到的性能与perf所的到的性能有很大的差距。这是由于fio软件架构的问题,所以不适用于单个线程来操作多块盘。因此在评估单个线程(单核)的能力的时候,一般选用perf作为测试工具。若为多个线程对应操作多块盘,则无需顾虑。在这种情况下,fio_plugin与perf结果无差异。

常见问题

1 通过使用fio和perf对SPDK性能评估,得到的结果不同,大部分的时候perf所得到的性能会比fio所得到的性能要高。

两种工具最大的差别在于,fio是通过与Linux fio工具进行集成,使其可以用来测试SPDK的设备,而由于fio本身架构的问题,不能充分发挥SPDK的优势,例如fio使用Linux的线程模型,在使用的时候,线程仍会被内核调度。而对于perf来说,是针对SPDK定制的性能测试工具,因此在底层,不仅是I/O操作会通过SPDK进行下发,同时一些底层架构都是为SPDK所设计的。例如刚刚所提到的线程模型,perf中是使用DPDK所提供的线程模型,通过使用CPU的亲和性将CPU核与线程捆绑,不再受内核调度,因此可以充分发挥SPDK下发I/O时的异步无锁化的优势。这就是为什么perf所测得的性能要比fio的高,因此,在同等情况下,我们更推荐用户使用perf工具对SPDK进行性能评估。

2 对SPDK和内核的性能评估时,虽然性能有所提升,但是没有看到SPDK官方所展示的特别大的性能差异。

首先,如问题1中所述,不同的工具之间得出的性能结果是不同的,另外最主要的因素还是硬盘本身性能瓶颈所导致的问题。例如,使用2D NAND的P3700,本身的性能存在一定的瓶颈,因此无论是SPDK驱动还是内核驱动,都会达到较高的IOPS。

如果我们换用更高性能的硬盘,例如使用3DXpoint的Optane(P4800X),便会发现很大的性能差异。因此,硬盘性能越高,SPDK所发挥出的优势越明显,这也是SPDK产生的初衷,本身就是为高性能硬盘所订制的。我们用下面这幅图来说明问题:

图1采用了基于裸盘的fio_plugin,使用单个CPU核,对单盘测试random read的结果。我们可以清楚地看到,用P4800X来测试的时候,无论qd增加多少,Kernel所能到的性能都是在300K+的IOPS。已经达到Kernel的最大能力,而SPDK可以轻松达到接近500k的IOPS。

此外,我们再普及两点额外的知识:

  • 对于评估以2D NAND、3D NAND介质的硬盘,例如P3700、P4500,一般情况下,为了达到磁盘的最高性能,通常会选择较高的qd(queue depth),通常qd=128即可,已经达到SPDK发I/O的最高效率。如果在128之上再增加qd,通常IOPS不会再有所增加,反而会增加单个I/O的latency。因此推荐使用qd=128。但对于新介质3DXpoint的硬盘,通常qd为8的时候,就已经可以达到一个最高值,因此若测试Optane(P4800X)的性能,通常推荐使用qd=8,而不是128。
  • 通常以2D NAND、3D NAND为介质的磁盘,在测试write的性能时,会有一些不稳定且虚高的现象,常见为测到的IOPS结果远远大于specification里的最高值,这是由于磁盘介质本身的问题。因此在测试此类磁盘时,为了避免上述现象,通常会在测试之前做precondition。通常做法为:在格式化之后,对磁盘不断进行写操作写满整个磁盘,使写入进入稳态。以P3700 800GB为例,通常我们会先顺序写两小时(4k),之后再随机写一小时(4k)。

总结

目前,SPDK被越来越广泛地应用到各个实际的应用场景中,相应的反馈和需求越来越多,相应的工具开发也提上了日程。在不久后的将来,SPDK会推出更多相应的生态工具,打造更加完备的用户态生态系统。

参考文献

[1] https://github.com/spdk/spdk/tree/master/examples/nvme/fio_plugin
[2] https://github.com/spdk/spdk/tree/master/examples/bdev/fio_plugin

作者:

周雁波
Intel 存储软件工程师
主要从事SPDK软件开发工作

刘孝冬
Intel 存储软件工程师
主要从事SPDK以及ISA-L软件开发工作

原文地址:DPDK开源社区

发表评论

电子邮件地址不会被公开。 必填项已用*标注