io_uring自2019年1月初提出后,目前已合入Linux v5.1版本,SPDK也在用户态通用块层(bdev),建立了uring bdev的设备。像其他存储设备对应的bdev一样,比如HDD, NVMe SSD, Optane SSD等等,可以灵活地将uring bdev配置到对应的应用和服务中。如图1可以将NVMe SSD分别配置成不同的bdev类型,给到SPDK的bdevperf测试工具:
图1:SPDK支持不同的Bdev
首先,回顾下SPDK (Storage Performance Development Kit) 的出发点,为了充分使用到CPU的能力和发挥出高速NVMe SSD的性能,SPDK开发了用户态的NVMe驱动,并引入了异步并发、轮询、无锁、单线程Run-To-Completion等优化。相关的重点优化如图2:
图2:SPDK NVMe用户态驱动优化
基于这些优化,SPDK可以很好地在CPU Core的处理能力和NVMe SSD的处理能力之间达到最理想的平衡。如图3,具体来说,CPU Core(或者更准确说单个CPU Core)执行SPDK的用户态驱动,去处理一个NVMe SSD,通过异步批量下发IO同时轮询IO完成状态。当处理完1个NVMe SSD时,CPU Core还有多余的处理能力,可以按同样的方式去处理更多的NVMe SSD。这里体现的是SPDK用户态驱动的Scale Up的能力,当CPU Core的处理没有达到上限的时候,整体的IOPS会随着NVMe SSD数量的增加而线性增加。等到总体IOPS随着更多NVMe SSD的增加而趋于稳定的时候,说明CPU Core (单个CPU Core) 的处理能力达到上限了。
图3:基于SPDK的单核多盘部署
所以除了SPDK能提供到低延时、高吞吐的优势,同时还能更好地使用到CPU Core的能力。尤其在需要计算和存储混合部署的场景中,对CPU资源的使用比较紧张的情况下。
回到io_uring,类似的优化包括轮询、异步、减少Copy等等也有在io_uring中实现,以此来提高内核的块设备IO处理能力,如图4。
图4:io_uring的优化
针对大家关心的io_uring和SPDK用户态驱动的性能对比,在2019 SDC的分享中,也有涉及到,从IOPS和延时两个角度来看,具体来说:
以单CPU Core处理能力来看,如图5。在同一个CPU Core上,通过SPDK用户态NVMe驱动可以挂载多达21个Optane P4800X SSD,达到千万级的IOPS,而io_uring最多可以挂载4个Optane P4800X SSD。详细的测试配置参考图7。
图5:单CPU Core,io_uring与SPDK对比
如果我们不考虑CPU Core的使用和限制,从打满单个NVMe SSD角度看,即使在libaio异步处理的情况下,同样可以占用多个CPU Core,分配多个FIO jobs,设置比较高的队列深度,比如常规的 4 jobs * 64队列深度/job,也通常可以把单个NVMe SSD打满。所以在这里,我们更关心的是,在单CPU Core下能输出的最高IOPS的能力。
从单个IO延时来看,如图6,以Optane P4800X SSD为例,SPDK相对io_uring也有近60%的优化。
图6:单IO延时,io_uring与SPDK对比
相关的测试信息如下:
图7:测试配置
总体而言,本文通过介绍新的内核io_uring技术,到回顾了SPDK用户态NVMe驱动,给出了SPDK和io_uring的对比。这个测试使用的是SPDK NVMe perf程序,在SPDK v20.07 release之后, 编译后的程序在SPDK 目录中的位置是:build/examples/perf。目前这个程序也已经支持用三种模式,即aio,io_uring以及SPDK NVMe用户态驱动来测试NVMe SSD。有条件的也可以用该perf程序进行单核测试多盘,看看在不通过SPDK bdev块设备层的时候,三种模式的性能对比。在我们设计和实现高性能的存储方案的时候,驱动是最重要也是最基础的一个层次。在驱动之上,还需要构建高效的软件层次,比如通用块层、协议对接层、应用服务层和业务层。SPDK能提供的,不仅仅是高性能的驱动层,同样有高性能的应用框架来提供通用块层和协议层,以此来适配更上层的业务。