当前位置: 首页 > 科技观察

桃李春风一杯酒,江湖十年一夜雨——老手夜话DPDK

时间:2023-03-16 17:26:43 科技观察

20年一眨眼。科技发展日新月异,从当初ixp1200的爽快体验,到如今的DPDK,智能网卡如火如荼。我也从过去的青涩少年变成了两鬓微霜的民工。午夜梦回,感叹人生如逆行的同时,心中也有许多思绪。Prequel2000是网络处理器的黄金时代。当时Intel也有一款名为IXP1200的NetworkProcessor产品,主要是通过一个可编程的专用引擎来加速网络数据包处理。IXP1200/2400/2800有N个微引擎用于编程。但是编程难度很大,尤其是在高并发的情况下,不容易调试。先来看看IXP1200和2800的架构图:IXP1200是第一代试水产品,只有6个微引擎。它的整体频率也较低,大约为233Mhz,所以只支持千兆网络线速。IXP2800已经发展到16个微型引擎。微型引擎的频率已增加到1.2Ghz。可支持10G网络线速。同时支持多种加密算法加速引擎。该产品线于2007年出售给Netronome,至今仍然存在,并且已扩展到60个或更多微型引擎。https://www.netronome.com/products/agilio-fx/每个微引擎内置4-8个硬件线程,每个线程可以发起一次收包操作,然后进入等待模式。调度程序调度其他硬件线程运行。直到I/O操作完成,相应的信号被重置为可调度的(注意这都是硬件逻辑)。下面是微引擎的内部架构。可以看到这个微引擎小而全,甚至还有一个CAM(Content-addressablememory)。寄存器分为几类:用于计算的通用GPR和用于IO的xfer寄存器。代码有4k空间。有一定大小的本地缓存LocalMem。还有一些与中断类似但又不完全相同的信号机制。许多非常精巧的代码也可以写在这个蜗牛壳中,包括复杂的有限状态机。下面是一个代码示例。这段代码估计大部分人都看不懂。这实际上是微引擎编程的一个瓶颈——可读性差和学习曲线陡峭。微引擎中的资源(各种寄存器、信号)非常有限,基本上需要手动优化,开发人员编码时如履薄冰。注册疲惫是我当时的噩梦。绞尽脑汁,释放一些资源。高学习曲线直接导致开发生态非常小。同时,开发工具和调试工具必须是专有的。直接导致开发效率低下。这些也是专用ASIC和网络处理器的常见问题。挑战来了。X86CPU主导控制面,而数据面则长期受制于FSB和PCI/PCIE带宽限制。2010年后,随着新一代X86CPU性能的不断提升(FSB被取代,DMI带宽不断提升)和PCIE2.0的引入。所以不禁让人好奇。使用X86是否可以实现10G线速处理?这在当时是一个巨大的疑问。一般认为很难做到。先来看看FSB的去除。FSB的全称是Front-sidebus。如下图所示,它主要负责连接CPU和北桥内存控制器的总线技术。FSB位于北桥(通常是内存控制器集线器)和CPU之间。FSB不仅控制着对内存的访问,也是PCIE通信的唯一途径。性能不可水平扩展。作为控制平面是没有问题的。但如果它被用作数据平面,它就成为主要瓶颈。让我们看看之后的Sandybridge微架构是什么样子的。去掉了前端总线,内存控制器直接集成到CPU中,PCIE也升级到2.0(这意味着每条通道的带宽升级到4Gbps)。使用X86作为数据平面解决方案有很多好处:X86芯片通常有18个月的更换周期,可以让性能车在18个月内得到更新。一个典型的例子是aes-ni,每一代aes-ni指令都对其进行了增强。这同样适用于sse/avx/avx2/avx512。(aes-ni属于X86的AES加密算法指令扩展)虚拟化技术也可以毫无障碍的使用,从而节省单独研发的成本。同时,因为是X86,所以整个技术生态是完整的。开发环境/调试环境不再需要使用专有的。通用性大大增强,升级效率和时间也大大提高。例如,可以使用最新最好的编译器技术。C语言的普及度也很高,学习曲线平缓。随着X86处理器Sandybridge一代的发布,之前的各种技术瓶颈似乎有了松动的迹象。VenkyVenkatesan(已故DPDK之父)心目中的新一代技术方案也逐渐成型。经过一段时间的内部审议,英特尔于2010-2012年完成了架构分析和设计。2013年dpdk社区正式上线,成为业界现象级产品。那么我们可以回顾一下Venky先生当时面临的挑战(X8610G线速)。10G线速基本等于15MPPS(即每秒1500万个数据包)。然后CPU有大约67.2ns的预算来转发一条消息。Sandybridge的主频达到2.2Ghz毫无难度。难度应该主要来自IO。FSB瓶颈已被替换。PCIE2.0已经开始支持。也支持2M/1G的大页!但是如果回过头来看软件,问题很多。这个目标是通过传统的内核协议栈完全无法实现的。当然,内核协议栈的设计理念并不是纯粹为了性能。多功能性也是一个重要的考虑因素。但是在这个特定的场景下,就成了最后的瓶颈。应对挑战DPDK是一个典型的从量变到质变的设计过程。它本质上是许多优化方法的集合。单一的优化方法实际上以前就存在过。比如bypasskernel的netmap。但是单一的优化方法并不足以使性能提升到一定程度的质变。DPDK是所有可用优化方法的集大成者,将X86处理器的网络处理能力推向了一个新的高度。我们可以将DPDK的优化方式列举为(包括但不限于):Bypasskernelprotocolstack。通过uio/vfio将网络设备暴露给用户层,抛开公共内核路径,轻量级。(uio/vfio是Linux内核支持用户级驱动的编程框架)使用hugepages大大降低了TLBmiss带来的性能损失。具体可以参考(https://lwn.net/Articles/374424/)大量应用批处理来分摊单个消息的开销(比如使用simd优化网卡驱动)。批处理的优化思想是DPDK通用范式中极其重要的一个。放弃中断方式,直接使用轮询方式。这对于减少延迟非常重要。因为在PCIE总线上,一个中断也是一个TLP报文。中断过多也会影响真实数据(尤其是小包)的延迟,中断处理引起的上下文切换也会引起系统抖动。但轮询是对内存控制器和PCIERootComplex健壮性的考验。健壮性差的平台容易出问题。神奇的改DDIO,网卡直接DMAs数据到LLC(Last-LevelCache)。DDIO对于小包的性能非常重要。这在今天仍然是xeon独有的功能(在新一代CLX协议中实现了DDIO的超集)详情请参考《Linux代码阅读领域》上篇文章《Linux 系统性能评测基准系统配置及其原理》公众号。对齐,对齐,对齐。预取预取并再次预取。非常注意缓存优化。对齐主要针对CacheLine长度和PCIEDMA地址。PrefetchingPrefetch比较难掌握精确的时间点,需要反复实验才能找到最佳位置。详情请参考英特尔软件优化手册(https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-optimization-reference-manual.html)隔离Core可以防止Core参与操作系统的调度。减少抖动。禁止进程切换并尽量减少系统调用,这会导致严重的抖动。详情请参考之前X86微架构的公开文章(https://mp.weixin.qq.com/s/nkiE4CEo_zSN35I_qITAvQ)。随时随地优化。比如写转发。详情请参考英特尔软件优化手册。二阶递进分区设计模式被广泛使用。尽量避免内核间通信(例如内存池/本地池等)。详情请参考DPDK官方文档。大量使用无锁队列和相关复杂的数据结构设计。例如著名的rte_ring。详情请参考DPDK官方文档。经过这样的递进联合优化,DPDK终于达到了性能的巅峰。但故事并没有就此结束。X86还有一个比较突出的问题,就是关于价格。那么每颗X86至强核心的价格也不便宜。因此,当一些业务流程逐渐沉淀和固化后,可以将其转换成ASIC重新加工。这就催生了各种Smart网卡,兜了一圈又回到了IXP。只是微引擎(或类似的可编程组件)现在被集成到网卡中。这些恰恰证明了技术的发展是一个螺旋式的过程,始终是围绕性能/价格进行动态的平衡调整。DPDK与内核的关系这一主题通常是DPDK被广泛误解的领域。我觉得既有竞争关系,也有非常密切的合作关系。首先让我们谈谈竞争。DPDK与Linux内核竞争的只是Linux内核协议栈中报文转发过程的一小部分。那么这部分是由于Linux内核协议栈常年性能非常低下所致。当然,这也是Linux内核的一些设计哲学造成的。其实不是设计错误,而是目标不同。所以这部分确实存在竞争关系,但值得一提的是,DPDK还催生了Linux内核中新的数据包处理框架XDP、AF_XDP等新兴技术。既可以看作是竞争,也可以看作是晋升。对于一些内核协议栈维护者过于戏剧化的行为,我觉得看看就好了。毕竟想想DPDK的编码风格和开发管理流程,大部分还是遵循内核社区的。那么这部分的合作呢?事实上,它非常多。首先,DPDK使用的所有基础设施:UIO/VFIO/IOMMU框架都是内核提供的。Hugepage和Systemmap地址查找都依赖于内核中的所有sysfs,不用说都依赖它们。电源管理框架完全植根于cpufreq/idle这两个核心子系统。每次新一代处理器支持周边生态linkerloaderdebugercompilerperf等虚拟化支持也依赖于kvm/qemu。你可以想到更多。展望未来在通信技术飞速发展的今天,DPDK面临着许多新的挑战:使用如此优质的内核进行轮询,浮点单元和极端乱序引擎还没有充分发挥其效用,而且价格还是不便宜。它将面临DPU的挑战。最后应该是多种解并存的状态。100%的cpu使用率很难监控真实的cpu使用率,能耗也是一个问题。当然,社区中已经讨论了很多这方面的改进解决方案。为了扩大生态,开源和高度健壮的协议栈仍然是稀缺的。也是一个生态问题,如何优化与控制面的接口也是一个大方向。CloudNative大趋势下,如何进化和适应。这些问题还有待整个DPDK社区的不断努力才能得到解决。参考https://www.dpdk.org/wp-content/uploads/sites/35/2014/09/DPDK-SFSummit2014-HighPerformanceNetworkingLeveragingCommunity.pdfhttp://dpdk.orghttps://www.intel.com/content/www/us/en/io/data-direct-i-o-technology-brief.htmlhttps://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-optimization-reference-manual.htmlhttps://lwn.net/Articles/374424/作者简介海外资深码农Liam,涉足应用密码学、CPU微架构、高速网络通信等领域。本文转载自微信公众号“Linux代码阅读领域”,可通过以下二维码关注。转载本文请联系Linux代码阅读领域公众号。