跳转至

DPDK

1 DPDK简介

  • DPDK是一个性能出色的包数据处理加速软件库。它大量利用了有助于包处理的软硬件特性, 如大页、 缓存行对齐、 线程绑定、 预取、 NUMA、 IA最新指令的利用、 Intel DDIO、 内存交叉访问等。
  • DPDK最初的动机很简单, 就是证明IA(Intel Architecture)多核处理器能够支撑高性能数据包处理。 随着早期目标的达成和更多通用处理器体系的加入, DPDK逐渐成为通用多核处理器高性能数据包处理的业界标杆。

1.1 传统网络设备缺陷

以Linux为例,传统网络设备驱动包处理的动作可以概括如下: 1. 数据包到达网卡设备。 2. 网卡设备依据配置进行DMA操作。 3. 网卡发送中断,唤醒处理器。 4. 驱动软件填充读写缓冲区数据结构。 5. 数据报文达到内核协议栈,进行高层处理。 6. 如果最终应用在用户态,数据从内核搬移到用户态。 7. 如果最终应用在内核态,在内核继续进行。 随着网络接口带宽从千兆向万兆迈进,原先每个报文就会触发一个中断,中断带来的开销变得突出,大量数据到来会触发频繁的中断开销,导致系统无法承受,因此有人在Liux内核中引入了NAPI机制,其策略是系统被中断唤醒后,尽量使用轮询的方式一次处理多个数据包,直到网络再次空闲重新转入中断等待。NAPI策略用于高吞吐的场景,效率提升明显。

1.2 DPDK优化技术

  • 轮询:这一点很直接, 可避免中断上下文切换的开销。 之前提到Linux也采用该方法改进对大吞吐数据的处理, 效果很好。 在第7章, 我们会详细讨论轮询与中断的权衡。用户态驱动, 在这种工作方式下, 既规避了不必要的内存拷贝又避免了系统调用。 一个间接的影响在于, 用户态驱动不受限于内核现有的数据格式和行为定义。 对mbuf头格式的重定义、 对网卡DMA操作的重新优化可以获得更好的性能。 而用户态驱动也便于快速地迭代优化, 甚至对不同场景进行不同的优化组合。 在第6章中, 我们将探讨用户态网卡收发包优化。
  • 亲和性与独占: DPDK工作在用户态, 线程的调度仍然依赖内核。 利用线程的CPU亲和绑定的方式, 特定任务可以被指定只在某个核上工作。 好处是可避免线程在不同核间频繁切换, 核间线程切换容易导致因cache miss和cache write back造成的大量性能损失。 如果更进一步地限定某些核不参与Linux系统调度, 就可能使线程独占该核, 保证更多cache hit的同时, 也避免了同一个核内的多任务切换开销。
  • 降低访存开销: 网络数据包处理是一种典型的I/O密集型(I/O bound) 工作负载。 无论是CPU指令还是DMA, 对于内存子系统(Cache+DRAM) 都会访问频繁。 利用一些已知的高效方法来减少访存的开销能够有效地提升性能。 比如利用内存大页能有效降低TLB miss, 比如利用内存多通道的交错访问能有效提高内存访问的有效带宽, 再比如利用对于内存非对称性的感知可以避免额外的访存延迟。 而cache更是几乎所有优化的核心地带,这些有意思而且对性能有直接影响的部分, 将在第2章进行更细致的介绍。
  • 软件调优:调优本身并不能说是最佳实践。 这里其实指代的是一系列调优实践, 比如结构的cache line对齐, 比如数据在多核间访问避免跨cache line共享, 比如适时地预取数据,再如多元数据批量操作。 这些具体的优化策略散布在DPDK各个角落。
  • 利用IA新硬件技术: IA的最新指令集以及其他新功能一直是DPDK致力挖掘数据包处理性能的源泉。 拿Intel ® DDIO技术来讲, 这个cache子系统对DMA访存的硬件创新直接助推了性能跨越式的增长。 有效利用SIMD(Single Instruction Multiple Data) 并结合超标量技术(Superscalar) 对数据层面或者对指令层面进行深度并行化, 在性能的进一步提升上也行之有效。 另外一些指令(比如cmpxchg) , 本身就是lockless数据结构的基石, 而crc32指令对与4Byte Key的哈希计算也是改善明显。
  • 充分挖掘网卡的潜能: 经过DPDK I/O加速的数据包通过PCIe网卡进入系统内存, PCIe外设到系统内存之间的带宽利用效率、 数据传送方式(coalesce操作) 等都是直接影响I/O性能的因素。 在现代网卡中, 往往还支持一些分流(如RSS, FDIR等) 和卸载(如Chksum, TSO等) 功能。 DPDK充分利用这些硬件加速特性, 帮助应用更好地获得直接的性能提升。
  • 此外还有DPDK I/O虚拟化,业界广泛使用的两种主流方式, SR-IOV和Virtio。

2 DPDK主要模块

  • 核心库Core Libs, 提供系统抽象、 大页内存、 缓存池、 定时器及无锁环等基础组件。
  • PMD库, 提供全用户态的驱动, 以便通过轮询和线程绑定得到极高的网络吞吐, 支持各种本地和虚拟的网卡。
  • Classify库, 支持精确匹配(Exact Match)、最长匹配(LPM) 和通配符匹配(ACL),提供常用包处理的查表操作。
  • QoS库, 提供网络服务质量相关组件, 如限速(Meter) 和调度(Sched)

DLPDK模块