《深入浅出DPDK》读书笔记(十六):DPDK应用篇(基于DPDK的存储软件优化:SPDK)
Table of Contents
基于DPDK的存储软件优化
DPDK技术的诞生虽然主要是为了加速网络报文(小包)的处理,但是相关技术亦可以应用到存储系统中,用以提高存储系统中网络的效率,继而提升整个系统的性能。由于DPDK技术只关注OSI协议的第二和第三层,为此使用到存储中,需要做一些额外的工作。本章将详细介绍如何把DPDK技术应用到存储的一些领域中,并了解所面对的挑战和机会。
首先让我们简单回顾一下DPDK的主要特点。DPDK作为一个高速处理网络报文的框架,提供了以下重要的思想和技术。
- ❑用户态的网络驱动:使用轮询方式的用户态网络驱动,替换了基于中断模式的内核态网络驱动。
- ❑基于大页的内存管理:DPDK的大页机制是预先分配一块内存,进行独立的内存管理。
- ❑基于pthread的CPU调度机制:目前DPDK使用了pthread开发库,在系统中把相应的线程和CPU进行亲和性的绑定,这样,相应的线程尽可能使用独立的资源进行相关的数据处理工作。
回顾DPDK的设计框架,我们可以自然而然地联想到把DPDK运用在高性能计算或者存储系统上。特别是在网络数据交换密集的应用中,如果数据之间没有紧耦合的情况下,DPDK的特性可以有助于提高整个数据处理系统的性能,比如提高IOPS、减少时延。不过,在实际应用中,我们要达到这样的目标并不那么容易。下一小节将介绍一些基于DPDK的网络存储所带来的挑战。
180.基于以太网的存储系统
以太网已经成为当今存储系统中不可缺少的一环。这些存储中的网络大致可以分为两个部分,内部网络和外部网络。内部网络主要是整个存储系统中各个节点之间的通信(如果存储系统由集群构成)。外部网络是对外的接口,提供相应的服务。
目前,DPDK相关技术主要用于以太网协议的网卡优化。为此,我们这里提到的网络存储系统,都建立在由以太网组成的网络上。图15-1给出了一个基于以太网协议的网络存储应用示例。存储阵列或者服务器利用已有的网络,采用不同的交互协议来提供各种存储服务。这些存储服务可以分为以下几类:文件存储(f ile)、块存储(block)和对象存储(object)。下面是几种常见的网络协议:
- 1)iSCSI协议:运行在以太网的SCSI(Small Computer System Interface,小型计算机系统接口)协议,主要提供块设备服务。
图15-1 基于以太网的存储系统
- 2)NAS协议:可以运行在以太网上提供文件服务。
- 3)Restful协议:运行在HTTP之上的(http协议亦可以工作在以太网上),提供相关对象存储服务。
- 4)运行在以太网协议的FC(Fibre Chanel)协议FCOE:用以访问传统的SAN(storage area network,存储区域网)提供的存储服务。
由于下面要介绍一套DPDK的iSCSI软件方案,这里先简单介绍一下iSCSI协议。iSCSI(internet Small Computer System Interface)是由IEETF开发的网络存储标准,目的是用IP协议将存储设备连接在一起。通过在IP网上传送SCSI命令和数据,ISCSI推动了数据在网际之间的传递,同时也促进了数据的远距离管理。由于其出色的数据传输能力,ISCSI协议被认为是促进SAN市场快速发展的关键因素之一。因为IP网络的广泛应用,ISCSI能够在LAN、WAN甚至internet上进行数据传送,使得数据的存储不再受地域的限制。ISCSI技术的核心是在TCP/IP网络上传输SCSI协议,它利用TCP/IP报文和ISCSI报文封装原来的SCSI报文,使得SCSI命令和数据可以在普通以太网上进行传输,如图15-2所示。
图15-2 iSCSI报文结构
因此,网络存储系统不仅仅依赖于网络性能,还依赖于后端的存储系统性能,两者的优化缺一不可。为此,我们需要综合考虑如何提高前端的网络通信和后端的存储设备上的数据处理效率。我们可以简单了解一下,现有的基于服务器的存储系统怎么处理相关的读写操作。假设有一个来自用户请求(如图15-3所示)的写操作,那么会有以下的流程:
图15-3 基于服务器的存储系统的写请求处理示意图
- 1)网卡收到相应的数据。
- 2)内核把相应的数据从内核态拷贝到位于用户态的daemon(守护进程)。
- 3)daemon守护进程调用写服务,要求内核写回存储设备。
- 4)为此相应节点的内核收到相应的请求,把数据从用户态拷贝到内核态,然后调用相应的存储驱动来进行写操作。
从上面的处理过程可以看到,在传统的网络存储中,一般的写操作将发生两次数据拷贝。第一次由网络传输引起,第二次由后端存储设备引起。当然,一些比较高端的存储系统会进行一些优化,例如使用零拷贝技术。目前Linux也提供了scatter-gather的DMA机制,这样可以避免内核空间到用户空间的数据拷贝,只需要把网卡的数据直接从网卡的缓存区拷贝到应用程序的用户态内存空间中,再把用户态的内存空间的数据直接由存储驱动写回设备。但是,在与基于内核的存储系统进行交互中,不是所有的数据拷贝都是可以避免的。因此,如何提高前端和后端的性能,是所有网络存储系统不得不面临的挑战。
181.以太网存储系统的优化
下面系统地解释一下如何利用DPDK解决网络协议栈的技术问题。图15-4显示了利用DPDK技术来构建和优化存储系统中的各个模块。
首先,我们可以利用DPDK来优化网络驱动,通过无锁硬件访问技术加速报文处理,例如Intel网卡的Flow Director技术将指定的TCP流导入到特定的硬件队列,针对每个Connection(连接)分配不同的TX/RX队列。
图15-4 网络存储优化
其次,在Socket协议层,我们可以利用DPDK去除共享数据结构的内核锁,降低内核驱动的延时和上下文切换,加速数据处理,从而实现高效的用户态网络协议栈。当然,即使有了用户态网络栈的支持,从程序开发的角度来讲,我们还必须保持这个用户网络栈和内核态网络栈接口的兼容性。理想情况下,所有上层应用程序可以不修改已有的代码,就无缝地迁移到用户态的软件栈,这样对于软件开发的影响可以降低到最小。
另外,我们还可以使用DPDK技术实现用户态下的存储设备驱动,最大限度地减少内存拷贝和延时,提高数据吞吐量。
毫无疑问,DPDK对于网络报文的处理,尤其对小尺寸的网络包(包大小低于1500字节)和并发的网络连接有很大的性能提升。网络存储系统可以使用DPDK技术来实现用户态的网络驱动,以避免内核和用户态之间由于数据拷贝所带来的开销。这样,就正好解决了网络存储中的“网络部分”的性能瓶颈。除此以外,DPDK也可以用来实现用户态的存储驱动来解决用户态数据到具体存储设备的开销。另外,在设计新的网络存储服务的时候,我们需要关注DPDK的并行数据处理框架,利用DPDK的编程框架更好地发挥DPDK由于并行带来的好处。另外,无论是提供文件、对象或块服务,网络存储都需要相应的网络栈,即利用“已经存在的物理网络”加“上层的的网络协议”。所以,在把DPDK技术应用到基于以太网的网络存储中之前,我们需要考量已有的DPDK是否能够提供一个完整的网络协议栈。
目前的DPDK没有提供正式支持的用户态网络协议栈,仅提供了使用轮询工作模式的诸多以太网卡的驱动,可以进行简单的以太网收发包的工作。这意味着DPDK只能工作在OSI 7层协议的第2层(link)和第3层(IP)上,还没有提供基于第4层(协议层)相关的网络传输协议,比如TCP/IP协议。因此,对于需要TCP/UDP/IP协议的应用程序,目前还无法直接使用DPDK。但幸运的是,尽管DPDK社区还没有官方支持的TCP/IP栈,但已经有些商业(TCP/IP)软件栈提供了这样的方案,并已经有一些和DPDK展开了密切的合作,还建立开源项目专门集成相关的开源用户态网络协议栈,诸如mtcp[Ref15-1]、libuinet[Ref15-2]、OpenFastPath[Ref15-4]等。这些开源的TCP/IP都有不同的应用场景,尽管不像Linux内核中的TCP/IP栈那么通用和稳定,但是都能在一定的应用场景中提供超过现有Linux内核态协议栈的性能,因此都有不小的受众。
SPDK介绍
《SPDK:存储性能开发套件(Storage Performance Development Kit)介绍》
182.SPDK介绍
为了加速iSCSI系在IA平台上的性能,Intel专门提供了一套基于IA平台上的软件加速库和解决存储方案SPDK(Storage Performance Development Kit),它利用了DPDK框架极大提高了网络存储协议端和后端的存储驱动的性能。SPDK架构包含以下内容(如图15-5所示):DPDK的代码库,一个用户态的TCP/IP栈,一些用户态的存储相关的驱动(比如用户态的基于NVME的SSD驱动),一个基于DPDK和用户态TCP/IP栈的iSCSI target的应用程序。目前,Intel已经将SPDK开源,并公开了基于NVME协议的用户态的SSD驱动[Ref15-5],接下来会逐步开源其他的模块。
图15-5 SPDK架构图
15.3.1 基于DPDK的用户态TCP/IP栈
前面已经提到,DPDK只提供了对OSI 7层协议的第2层和第3层的支持,为此需要第4层以上协议(主要是需要TCP或者UDP)支持的应用程序无法直接使用DPDK。为了弥补这一个问题,SPDK中提供了一个用户态的TCP/IP协议栈(libuns)。为了高效地利用DPDK对于网络报文快速处理这一特性,一个有效的网络协议栈必须解决兼容性和性能问题。
(1)兼容性
一般而言,应用程序都是调用系统已经存在的套接字接口(SOCKET API)。举个例子,图15-6给出了基于统一的SOCKET API,但是使用了不同的TCP/IP协议栈的比较示意。我们可以看到图的左边主要是使用了基于Linux内核的TCP/IP协议栈,用户所发送数据需要通过内核协议栈的协助,这样就会产生用户态和内核态的上下文切换,并且产生用户空间和内核空间之间的数据拷贝。而图的右侧显示了基于用户态的软件协议栈,比如DPDK、UDS等,应用程序必须绕过内核所提供的TCP/IP/UDP协议栈。这是一个比较简单的方法,通过应用程序调用自定义的接口,这样的方法降低了实现上的难度,但是不兼容已有的应用程序,已有的应用程序必须做代码上的修改,才能使用新的用户态网络协议栈。因此,用户态的TCP/IP/UDP协议栈,必须为上层的应用提供一个友好的机制,让用户使用已有的接口,但是可以绕过现有内核的实现。这样的方法有很多种,SPDK中的libuns提供了以下的解决方案:监控打开socket操作相关的文件描述符(f ile descriptor),当调用标准库操作的时候(诸如linux下是glibc),进行截获,一旦发现是监控的文件描述符,就调用用户态的函数。
图15-6 内核态和用户态网络实现比较
(2)性能
为了保持与已有的DPDK的管理机制兼容,我们需要对相应的TCP/IP栈进行优化,LIBUNS就很好地利用了DPDK的优势。图15-7给出了在FreeBSD系统中,应用程序如何调用网络服务。应用程序在用户态使用线程安全的套接字库。在内核中为了实现相应的功能,采用了一系列线程来访问如下的一些层:套接字层的状态机、传输层的协议栈(UDP, TCP等)、IP层、link等。从图15-7中我们可以看出,在每一层中都有很多锁的机制来保护共享的资源,以保证资源被访问的正确性。需要注意的是,当多线程应用同时访问TCP/IP栈的时候,由于存在很多的竞争,会导致协议栈的性能下降。
再让我们了解图15-8中Libuns的协议栈,应用程序调用兼容的套接字软件库(包含在libuns.so文件中),而套接字层的状态机、传输层的协议栈(UDP, TCP等)、IP层等实现都转移到了用户态。因为Libuns在实现中保证了所有资源都是由应用程序独享的,每层的锁机制都被去除了,这就减少了锁竞争所带来的代价。Libuns能这么做的原因在于,DPDK提供了相应的机制允许CPU可以直接绑定在网卡的队列,负载不同的接收和发送。如图15-8所示,每个socket layer的实体的队列处理可以使用DPDK的队列管理功能。
图15-7 FreeBSD IP层协议栈
图15-9给出了Libuns的详细架构:
- ❑Diven by application:完全由应用程序驱动。
- ❑Puring polling solution:采用DPDK支持的轮询模式的包处理。
- ❑Single Rx Queue:Libuns使用了单一的队列来接收数据,但是针对不同的应用程序线程,Libuns提供了独立的发送队列来发送数据。
- ❑Software Filters patches to individual TCP Flows:通过f low director以及共享ring的机制把数据发送给应用程序的不同线程。
- ❑Sperate Memory Pools:针对应用程序的不同线程,Libuns提供了单独的内存池,因此访问内存不需要额外的锁保护机制。
- ❑No Locks:不同的线程可以使用不同的发送队列,因而相应的锁可以被去除。
除了Libuns,还有一些其他的用户态协议栈可以选择。这里我们再介绍另一个开源项目MTCP。MTCP是一个针对多核架构设计的高可扩展的用户态TCP/IP栈的实现,针对高并发的连接和网络处理进行专门的优化。目前MTCP 3.0已经可以运行在DPDK之上,根据最新的测试,MTCP可以很好地利用DPDK对某些应用进行加速。
图15-8 Libuns的TCP/UDP/IP协议栈
图15-9 Libuns系统架构
在MTCP看来,原有的Linux内核态TCP/IP栈的实现主要存在以下问题:
- ❑由于文件的描述符(File Descriptor, FD)在一个进程内部都是共享的,因此不同的CPU核在处理FD的时候存在相关的竞争。这些竞争包括:共享的监听FD的队列(锁保护)、FD的管理、需要在共享的空间内寻找空闲的FD。
- ❑破坏了应用程序的局部最优原则,比如在基于per-core的包处理队列中,收到中断的CPU和最后实际处理网络数据读写的CPU不是同一个,这就带来大量的系统开销。
- ❑低效的批处理方式,比如accept/read/write等系统调用效率不高,不断地要进行上下文的切换,并引起cache的不断更新。另外,内核的TCP/IP栈处理报文的时候也很低效,对每个包都要进行内存的分配。
- 为了解决这些问题,MTCP采用了如下的解决方案来优化它所实现的用户态TCP/IP栈。
- ❑每个CPU工作在独立的资源上,FD和core绑定,每个core的FD都是私有的,有自己的FD监听队列,这样不同的CPU core之间不存在竞争。
- ❑基于内核态下的packet IO批处理变成在用户态进行批量处理,减少了与内核之间的上下文切换。
- 根据MTCP的论文[Ref15-6], MTCP在处理小包和高并发的时候还是非常高效的,有兴趣的读者可以去阅读MTCP的论文。笔者也曾尝试了一下MTCP,但是发现MTCP在易用性方面还需要加强,MTCP也存在一些问题,例如:
- ❑目前只支持TCP协议,不支持UDP。
- ❑如果要使用MTCP,我们需要修改原有程序的代码。MTCP函数使用了前缀名为mtcp_的命名方式,替换原有的函数。比如正常的getsocket函数,MTCP提供了mtcp_getsocket函数,并且传入的参数也多一个MTCP特有的上下文参数。这导致当用户程序的网络模块的代码比较复杂的时候,代码移植的代价很大。另外,MTCP所提供的兼容BSD的socket接口也比较有限,某些函数并没有实现。
- ❑独立的FD管理也增加了管理成本。由于MTCP为了克服由于内核共享FD所带来的开销,让每个CPU核使用独立的FD。这就对应用程序提出了要求,使用MTCP所建立的FD只能在同一个CPU核上处理。暂时MTCP并没有支持CPU核之间的FD迁移。
这里我们还想再介绍另一个高性能的协议栈OpenFastPath(简称OFP)。它是一个开源的高性能TCP/IP协议栈的实现,目前OFP社区主要的成员包括有NOKIA、ENEA和ARM。OFP的开源TCP/IP协议栈的实现构建在OpenDataPlane之上(详细内容请参考[Ref15-7])。图15-10给出了OFP的架构图,我们可以看出应用程序如何调用相关模块显示功能,应用程序->OFP API -> ODP API -> Linux kernel -> ODP/DPDK的驱动软件或者固件。详细可以参考[Ref15-4]。
总的来讲,OFP的设计还是比较优美的,但是目前的OFP还存在一些问题,例如API的兼容性。OFP所提供的一些socket相关的API都使用了“OFP_”的前缀,因此应用程序也需要修改代码才能在OFP上执行。
图15-10 OFP架构
虽然在ODP中已经有一些DPDK的支持相关的PATCH,但是还没有进入ODP的主分支,所以,目前发布的OFP还不能利用DPDK进行测试。笔者曾经试图在OFP框架下使用ODP + DPDK,由于IP地址的解析以及OFP线程和DPDK的线程一起使用的适配问题,导致测试程序未能正常运行。读者如果要尝试这种方案,还需要多做一些研究工作。
183.用户态存储驱动
为了更好地发挥DPDK的优势,SPDK提供了一些用户态的存储驱动,诸如基于NVME协议的SSD的用户态驱动。NVME(Non-Volatile Memory Express)是一个基于PCI-e接口的协议。通过优化存储驱动,再配合经过DPDK优化的用户态协议栈,存储网络服务器端的CPU资源占用将被进一步降低。
1. 用户态NVME驱动工作机制
图15-11中,SPDK在IO管理上使用DPDK提供的PMD机制和线程管理机制,一方面通过PMD避免中断,避免因上下文切换造成的系统开销,另一方面,通过DPDK的线程亲和特性,将指定的IO QUEUE绑定特定的DPDK线程,在线程内部可以实现无锁化,完全避免因资源竞争造成的性能损失。另外,SPDK还引入了DPDK内存管理机制,包括hugepage和rte_malloc以及rte_mempool,使内存管理更加高效稳定。
图15-11 用户态NVME驱动机制
SPDK所提供的用户态存储驱动提供了内核驱动相同的功能,但和内核驱动相比,存在以下的区别:
- ❑使用轮询工作方式。
- ❑提供了线程的亲和性绑定,避免资源竞争。
- ❑利用DPDK的内存管理机制,以及利用mmio的方法映射PCI设备上的寄存器和内存空间。当然,用户也可使用其他的内存管理机制,未必一定要使用DPDK的内在管理机制。
基于DPDK的用户态存储驱动和内核驱动相比,在功能方面不会有缺失,诸如在可靠性方面可以提供一样的功能,甚至可靠性更高,因为在内核中如果驱动发生故障,有可能导致内核直接崩溃,而用户态的驱动不会存在这样的问题。
2. 内核态和用户态NVME性能比较
目前市场上,采用NVME协议的SSD要比采用SATA和SAS协议的SSD,性能更快,主要体现在IOPS的大幅度提高和时延的大幅度降低。虽然采用内核来驱动基于NVME的SSD,性能也完全可以达到物理上的标称值,但是会消耗更多的CPU。而基于用户态的NVME的SSD驱动则可以降低CPU的使用,用更少的CPU来驱动NVME的SSD,也能达到同样的性能。这意味着在同样的CPU配置情况下,用户态的NVME驱动性价比更高。
为了验证这一点,笔者做了以下的实验,主要比较用户态和内核态NVME驱动的性能。实验环境配置如下:
- ❑实验机器搭载2P Xeon®E5-4650 2.7GHz(8 core)。
- ❑32GB RAM。
- ❑Ubuntu(Linux)Server(kernel version 3.17)。
- ❑配置4个基于NVME协议的Intel SSD:PC3700。(P3700的4KB随机读的标称最高速度是450K IOPS。)
图15-12给出了在使用单核情况下,SPDK的用户态NVME驱动和内核态NVME驱动的性能比较。可以看出在SSD被分成1,2,4,8,16个分区的时候,用户态NVME驱动总能达到英特尔P3700 NVME的性能上限,而内核态NVME驱动的性能比较差。单核的性能大概只有用户态NVME驱动的1/9左右。当然,使用内核态的NVME驱动,也可以达到物理的性能极限,那意味着要用更多的CPU核。
图15-12 对本地4个NVME的SSD进行4KB的本地随机读
此外,图15-13也给出了用户态和内核态NVME在使用单核情况下驱动1个、2个、4个SSD的性能情况。我们可以看出,用户态NVME驱动的性能基本是线性增长,而内核态NVME驱动的性能没有任何的增长。这充分说明了,和内核态NVME的驱动相比,用户态NVME驱动可以使用更少的CPU来完成同样高性能的NVME读写。性能的差别主要在于以下几点:
- ❑基于用户态NVME驱动进行相关读写时,不涉及任何的用户态和内核态的数据拷贝,不存在上下文切换。
- ❑在频繁读写下,polling model比interrupt model更有效。
- ❑通过内核驱动读写块设备,存在相关的锁机制,从而降低了性能。
- ❑内核态比较长的函数调用栈,大量消耗了CPU的执行时间。
- ❑用户态的NVME驱动可以把不同的CPU绑定在NVME设备的不同队列上,从而减少了CPU之间的竞争。
图15-13 用户态和内核态NVME在使用单核情况下驱动1个、2个、4个SSD的性能比较
184.SPDK中iSCSI target实现与性能
1. SPDK中iSCSI target实现
SPDK中提供了一个iSCSI target实现的用例,以体现使用DPDK在性能上确实有相应的提升。图15-14给出了SPDK中的iSCSI target实现图,iSCSI客户端的工作流程大致如下:
- 1)利用DPDK用户态的polling model driver,从网卡中获取数据。
- 2)数据经过用户态的TCP/IP栈,通过标准的socket接口,转给iSCSI target应用程序。
- 3)iSCSI target应用程序解析iSCSI协议,转化成SCSI协议,把数据请求发给相应的后端驱动。
- 4)后端驱动接收数据后,对真实的设备驱动进行相应的读写操作。
- 5)I/O请求完成后,相关返回数据交给iSCSI target应用程序。
- 6)iSCSI target应用程序把数据封装成iSCSI协议后,调用标准socket接口写回数据。
- 7)用户态的TCP/IP栈得到数据后,进行相应的TCP数据分装,调用DPDK的polling model driver。
- 8)DPDK polling model driver驱动具体的网络设备,把数据写入网卡。
基于SPDK iSCSI target端的应用对比传统的iSCSI target端的应用,区别在于:
- ❑传统的iSCSI target应用一般使用:内核态的iSCSI协议栈+TCP/IP协议栈+中断模式的网卡驱动,比如LIO。(当然也有一些iSCSI target使用用户态的iSCSI栈,比如TGT。)
- ❑SPDK中的iSCSI target使用的是:用户态的iSCSI协议栈+TCP/IP协议栈+DPDK用户态的polling model驱动。
图15-14 SPDK中iSCSI target端实现架构图
这样的好处在于,减少了用户态和内核态之间数据交换的代价。如果后台的驱动是用户态的,就可以减少两次可能的数据拷贝:第一次,发生在发送或者接收网络数据的时候;第二次,发生在读写存储设备的时候。
我们知道,无论使用用户态还是内核态的驱动都不可能超过存储设备物理上的读写速度。但是,通过软件优化的方案,我们可以减少相应的CPU的消耗。而基于SPDK的iSCSI target的加速方案,毫无疑问地减少了CPU的消耗。这样的话,和传统的iSCSI解决方案相比,SPDK的iSCSI target解决方案在达到同样服务质量的时候使用了更少的CPU。
2. 基于SPDK的iSCSI target性能分析
为了更好地反映基于SPDK的iSCSI target的性能,我们根据以下配置做了相关的iSCSI的性能测试实验:
- ❑iSCSI服务器端:Intel 2P Xeon®E5-4650 2.7GHz(8 core),32GB RAM, Ubuntu(Linux)Server12.04 LTS,2x Intel®82599 EB 10 GbE Controller。
- ❑iSCSI客户端:Intel I7-3960X 3.3GHz(6 core),8GB RAM, Windows Server 2008R2, 2x Intel®82599 EB 10 GbE Controller。
- ❑客户端和服务器端的网络连接:不使用交换机,点对点连接。
- ❑iSCSI负载配置:每个iSCSI发起者使用两个连接,每个连接分配两个LUN,每个LUN上运行一个IOMETER。
- ❑IOMETER配置:4个工作者分别绑定在core 0到3上,读写大小4KB, I/O depth 1到32。
图15-15和图15-16给出了基于SPDK的iSCSI和LIO的iSCSI的性能比较,我们分别测试了随机读和随机写在队列长度为1、2、4、8、16、32情况下的IOPS、时延、CPU核的使用率。从图中我们可以看到,SPDK的iSCSI能够达到和LIO相同的性能,但是使用的CPU要远远少于LIO;并且在时延方面,SPDK也要优于LIO。
图15-15 ISCSI 4KB随机读:SPDK和LIO的性能比较
图15-16 ISCSI 4KB随机写:SPDK和LIO的性能比较
图15-17 iSCSI 4KB随机读写(NVME后端)
为了更好地说明SDPK的iSCSI对于CPU利用率的提高,我们给出了以下的性能比较。在服务器端,我们部署基于NVME协议的SSD,采用同样的方法进行测试,但仅比较服务器端单核的性能。从图15-17我们可以看到,基于SPDK的iSCSI单核性能要远远优于LIO的iSCSI,其中读性能最高,可以达到LIO的7倍,即有650%的增长。并且我们可以看到随着服务器端CPU核配置的增加,SPDK几乎可以到达线性增长。
185.小结
本章介绍了DPDK技术在存储系统中的应用。DPDK最初的设计目的是加速网络报文处理,并提供了一套完整的内存管理机制、用户态CPU调度机制、用户态设备管理等机制。但是,在实践中我们发现DPDK的这些机制也可以应用到存储系统中,用于改善网络存储系统中的网络和存储设备的性能。当我们解决了应用DPDK技术的相关挑战后,尤其是成功实现用户态的TCP/UDP/IP栈和提供用户态的存储驱动后,我们惊喜地发现DPDK技术确实可以有效地提高存储网络的性能。
系列文章
《《深入浅出DPDK》读书笔记(三):NUMA - Non Uniform Memory Architecture 非统一内存架构》
《《深入浅出DPDK》读书笔记(四):并行计算-SIMD是Single-Instruction Multiple-Data(单指令多数据)》
《《深入浅出DPDK》读书笔记(六):报文转发(run to completion、pipeline、精确匹配算法、最长前缀匹配LPM)》
《《深入浅出DPDK》读书笔记(七):PCIe与包处理I/O》
《《深入浅出DPDK》读书笔记(八):网卡性能优化(异步中断模式、轮询模式、混和中断轮询模式)》
《《深入浅出DPDK》读书笔记(十):硬件加速与功能卸载(VLAN、IEEE1588、IP TCP/UDP/SCTP checksum、Tunnel)》
《《深入浅出DPDK》读书笔记(十一):DPDK虚拟化技术篇(I/O虚拟化、CPU虚拟化、内存虚拟化、VT-d、I/O透传)》
《《深入浅出DPDK》读书笔记(十二):DPDK虚拟化技术篇(半虚拟化Virtio)》
《《深入浅出DPDK》读书笔记(十三):DPDK虚拟化技术篇(加速包处理的vhost优化方案)》
《《深入浅出DPDK》读书笔记(十四):DPDK应用篇(DPDK与网络功能虚拟化:NFV、VNF、IVSHMEM、Virtual BRAS“商业案例”)》
《《深入浅出DPDK》读书笔记(十五):DPDK应用篇(Open vSwitch(OVS)中的DPDK性能加速)》
《《深入浅出DPDK》读书笔记(十六):DPDK应用篇(基于DPDK的存储软件优化:SPDK)》
相关阅读
《DPDK PMD( Poll Mode Driver)轮询模式驱动程序》
《DPDK笔记 RSS(receive side scaling)网卡分流机制》
《网卡多队列:RPS、RFS、RSS、Flow Director(DPDK支持)》
《Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO》
《ARM SMMU原理与IOMMU技术(“VT-d” DMA、I/O虚拟化、内存虚拟化)》
《KVM Virtio: An I/O virtualization framework for Linux(Linux虚拟IO框架)》
《Linux虚拟化KVM-Qemu分析(二)之ARMv8虚拟化》
《Linux虚拟化KVM-Qemu分析(三)之KVM源码(1)》
《Linux虚拟化KVM-Qemu分析(四)之CPU虚拟化(2)》
《在CentOS上进行虚拟化:QEMU、Xen、KVM、LibVirt、oVirt》
《ARM SMMU原理与IOMMU技术(“VT-d” DMA、I/O虚拟化、内存虚拟化)》
《KVM Virtio: An I/O virtualization framework for Linux(Linux虚拟IO框架)》