Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于DPDK(x86平台)应用性能优化实践

基于DPDK(x86平台)应用性能优化实践

原创
作者头像
用户1272933
发布于 2019-02-24 09:25:05
发布于 2019-02-24 09:25:05
4.4K00
代码可运行
举报
文章被收录于专栏:DPDK性能优化DPDK性能优化
运行总次数:0
代码可运行

产生性能瓶颈有多方面的原因,包括硬件(自身能力限制或BIOS设置不当)、操作系统(某些feature没打开)和软件。软件方面的性能瓶颈主要是由于编码不当导致,常见原因有以下几种:

  • 数据结构cache line未对齐,访问的数据跨cache line
  • 不恰当的内存操作
  • cache miss严重,经常跨socket访问数据
  • 锁竞争
  • 中断太多
  • context切换频繁

本文讲述了在编码时如何利用x86平台的特点(主要是内存方面)来避免性能瓶颈的技巧,并对性能优化给出一种思路。

UMA与NUMA

UMA(Uniform Memory Access),即统一内存访问。在UMA内存架构中,所有处理器通过一条总线共享内存,如下图所示:

因为UMA结构中,所有处理器均通过同一条总线访问内存,故访问内存所花时间是一样的。且访问时间与数据在内存中的位置无关。而在NUMA(Non Uniform Memory Access,非一致性内存访问)结构中,访问内存所需时间与数据在内存中的位置有关,每个处理器都有自己的本地内存,访问本地内存速度很快,通过共享总线可以访问其他处理器的本地内存。结构如图所示:

正如前面所说,在NUMA结构中,访问内存所需时间与数据在内存中的位置有很大关系。处理器访问自己的本地内存要比访问其他处理器的本地内存要快得多。DPDK支持NUMA架构,接下来主要介绍一些进行内存操作方面需要注意的地方。

减少内存拷贝

出于性能考虑,要最小化数据的内存拷贝。在写代码的时候,当遇见需要拷贝数据时,考虑有没有一种更好的解决方式替代,如传递指针而非整个数据结构;在需要使用strcpy和memcpy时,用rte_strcpy和rte_memcpy作替。

合理分配内存

在实时处理数据包转发的系统中,一般不建议在数据面进行动态内存分配,因为不停的申请和释放动态内存会使堆产生碎片,管理这样的堆开销很大。如果真的需要在程序中动态申请内存,要避免使用libc的malloc接口,使用DPDK提供的类malloc函数作为替代。DPDK主要提供三种内存模型:rte_malloc、rte_mempool、rte_memzone,它们的使用场景如下:

  • 需要使用malloc时,用rte_malloc
  • 需要高性能分配内存时,用rte_mempool
  • 当程序需要分配一大块内存,在程序的生命周期不释放,用rte_memzone

关于内存申请,通常的做法是在程序初始化阶段分配好固定大小内存,通过指针链表串连起来管理它的分配与回收。例如,NAT中的分片处理,当后续分片先于首片到达设备时需要先缓存起来,每次从链表头取出一个结点来缓存报文,当缓存报文处理完后,又把该结点“回收”到链表头部。

尽量访问本地内存

根据前面的介绍,在NUMA系统中,访问本地内存比访问远端内存更佳高效。如上图所示,一个运行在core0上的应用访问数字标号处数据的速度快慢从高到低为1 > 2 > 3 > 4。在程序运行时,要避免进行过多的远端内存访问,DPDK提供在指定socket上分配memory的API

如果内存充裕的话,可以考虑复制一份数据到另一个socket上来提升数据读取的速度。

数据结构设计

  • 成员变量从大到小排列,避免过多的padding。考虑如下两个结构体:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 struct s1
{
    int a;
    char b;
    char c;
};

struct s2
{   
    char b;
    int a;
    char c;
};

结构体s1的大小为8字节,结构体s2为12字节,在定义时不考虑padding的话,每个结构体变量会浪费4字节。

  • 避免数据结构跨cache line,一条cache line应当正好放下整数个(N≥1)对象。

红色标识的obj2被load在两条cache line,如果访问这个对象时cpu需要更多的时钟,在数据结构时应该避免。可以在定义数据结构时用宏__rte_cache_aligned或加入padding成员。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 struct s3
{
    uint32_t x;
    uint16_t y;
}__rte_cache_aligned;

struct s4
{
    uint32_t x;
    uint16_t y;
    uint16_t padding;
}

数据预取

一般访问CPU的cache效率最高,提前将需要处理的数据load到cache可以提高性能,但预取必须在合适的时间点发起,过早发起预取会导致数据还没有被使用就被替换出cache,最终适得其反,所以需要根据实际应用场景和多次尝试找到最合适的预取时间点。

通常在进行数据包处理时会先对数据包进行预取操作。DPDK提供的接口rte_prefetch0会触发cpu进行预取操作,如下是预取数据包的示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 /* Prefetch first packets */
for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) {
	rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[j], void *));
}
/* Prefetch and forward already prefetched packets */
for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) {
	rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[j + PREFETCH_OFFSET], void *));
	l3fwd_simple_forward(pkts_burst[j], portid);
}
/* Forward remaining prefetched packets */
for (; j < nb_rx; j++) {
	l3fwd_simple_forward(pkts_burst[j], portid);
}

其他技巧

  • 对于一些代码行数不多且经常被调用的函数,定义为静态内联函数(static inline function),可以省去函数调用开销
  • 分支预测,对于经常发生或不常发生的分支使用likely()/unlikely()来帮助编译器生成更加高效的可执行文件,减少cache miss

性能瓶颈分析的一般方法

上面提的一些技巧可以帮助在开发过程中规避部分性能陷阱,但仅仅做到这些是不够的,就像任何程序都有bug一样,性能瓶颈始终是存在的。通过阅读代码很难发现产生瓶颈的原因,这时候就需要借助一些测量工具来帮助定位原因了。

通常作性能瓶颈分析时需要找一个软件基准版本,给出一个metric值(通常由测试仪器给出,比如时延、吞吐量),然后再通过分析工具定位出产生性能缺陷的代码,反复修改这部分代码再给出一个metric值与之间的值作比较,直到metric值达到自己的预期为止。

Linux提供了很多开源工具来分析程序性能,比如iostat、perf、vmstat等。Intel也提供了一款专业的性能分析工具VTune帮助开发人员分析和定位程序性能瓶颈。Intel处理器内部有许多事件计数器,当有事件发生时对应的计数器加一,与程序性能相关的计数器有如下几种:

  • cache misses
  • 分支预测错误
  • DTLB misses
  • 长延时指令和异常

通过查看这些计数器值大小便可断定瓶颈原因,这是一种较底层的分析方法,需要对Intel CPU架构有所了解,且不能定位到产生瓶颈的具体代码行。VTune提供的另外一种分析方法Hotspots,能够帮助开发人员找出程序中消耗CPU最多的(热点)函数,通过这些列出的热点函数可以快速定位到代码行。通常使用Hotspots分析能够找出一般常见的性能瓶颈。

VTune提供Windows下的GUI和Linux下的CLI两种版本。我在项目中一般先用CLI版本的VTune采集运行程序机器的数据,然后将产生的结果移至windows下用GUI版本的VTune来分析,图形化的界面能够更利于定位分析。下面是利用VTune分析程序hotspots的demo:

1. 模拟测试环境,运行需要调优的程序;

2. 执行amplxe-cl,指定采集类型和目标程序,开始采集数据,运行结束后会在当前目录下生成类似r000hs名称的目录,里面存放的是收集的结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 ./amplxe-cl -collect hotspots -target-pid=29892

3. 将目录拷贝到windows下,用VTune打开文件r000hs.amplxe

VTune打开后,出现的是一个关于hotspots的视图(因为之前指定收集的类型为hotspots,如果指定其他收集类型比如cpu events,则会出现对应视图)。里面有多个标签页记录了在采集过程中最耗CPU时间的函数。

Summary标签页记录了程序性能的大概数据,包括CPU耗时,top hotspots和系统信息。

Bottom-up标签页按函数消耗CPU时间从大到小排序,并可以查看函数的调用栈,如果目标程序没有采用编译优化,VTune甚至能定位到具体代码行,通过这些信息就可以很容易找到哪些代码最消耗CPU时间了。

在性能调优时,最好使用未经编译器优化的版本测试,这样VTune能够帮助定位到具体的代码行。采集时间不宜过长,否则会导致VTune分析缓慢,一般设置为60s即可,可通过amplxe-cl的参数指定,具体使用方法参考http://software.intel.com/zh-cn/blogs/2010/11/10/amplxe-cl

总结

性能优化是个体力活又是一个细心活,需要反复的代码修改和测试数据才能找到性能瓶颈所在。熟悉底层开发环境和x86系统结构对性能优化有很大帮助,只有在了解开发环境之后才能写出跑得更快的代码,只有熟知CPU内部结构才能在优化时提供更多的线索,一款好的分析工具也是必不可少的。本文只是讲了性能优化技巧的冰山一角,更多的是要在实际项目中不断摸索积累经验,具体问题具体对待。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
高性能网关设备及服务实践
针对海量的网络流量,转发性能是我们最关键的一个方面,那构建高性能的后台服务器有哪些关键的技术和需要注意的地方。
鹅厂网事
2018/02/02
3.6K1
高性能网关设备及服务实践
一文看懂DPDK
从我们用户的使用就可以感受到网速一直在提升,而网络技术的发展也从1GE/10GE/25GE/40GE/100GE的演变,从中可以得出单机的网络IO能力必须跟上时代的发展。
Willko
2018/08/29
66.8K12
Linux用户态协议栈与DPDK构建高性能应用
这里使用了已经搭建好的dpdk环境,dpdk的搭建过程网上有很多教程可以参考,后面有空再做一篇dpdk环境搭建文章吧! (1)检查网卡状态
Lion 莱恩呀
2024/09/15
4910
Linux用户态协议栈与DPDK构建高性能应用
DPDK 网卡收包流程
NIC 在接收到数据包之后,首先需要将数据同步到内核中,这中间的桥梁是 rx ring buffer。它是由 NIC 和驱动程序共享的一片区域,事实上,rx ring buffer 存储的并不是实际的 packet 数据,而是一个描述符,这个描述符指向了它真正的存储地址,具体流程如下:
dpdk-vpp源码解读
2023/03/07
3.7K0
DPDK 网卡收包流程
learning vpp:内存管理和 DPDK API
本译文源自PANTHEON.tech公司技术博客文章《VPP 105: Memory Management & DPDK APIs》,在我们深入运用VPP的过程中,不免对其中涉及的各类技术与库——它们的实践应用、优势特性及对应API——产生诸多疑问。这篇针对性的文章恰好为我们详尽答疑,扫清困惑。很适合入门vpp的同学学习。如需查阅原文,欢迎直接点击文末阅读原文。
dpdk-vpp源码解读
2024/04/15
8790
learning vpp:内存管理和 DPDK API
下一代 TGW 从13Mpps到50Mpps性能优化之旅
本文作者:和广强,腾讯 TEG 后台开发工程师 0 导语 性能优化是一条既充满挑战又充满魔力的道路,非常幸运如今基于 X86 的性能优化方法及工具已经比较成熟,在 TGW 产品架构即将变革之际,我们结合 X86 常用的性能优化方法与工具,深入分析 DPDK 版本 TGW 转发架构与流程将 TGW 转发性能从 13Mpps 优化到 50Mpps;本文带你穿越下一代 TGW 性能优化之旅,快上车吧。 1 前言 目前腾讯突破“双百”里程碑(服务器超过 100W 台,带宽峰值超过 100T)其所承载的业务
腾讯技术工程官方号
2019/12/18
1.9K0
下一代 TGW 从13Mpps到50Mpps性能优化之旅
Vpp QoS Hierarchical Scheduler(2)
上篇讲解了Hqos基本知识点及vpp Hqos配置及基本流程框架,今天通过源码来分析Hqos实现逻辑。
dpdk-vpp源码解读
2023/03/07
1.5K0
Vpp QoS Hierarchical Scheduler(2)
使用 DPDK 和 GPUdev 在 GPUs上增强内联数据包处理
使用 GPU 进行网络数据包内联处理是一种数据包分析技术,可用于许多不同的应用领域:信号处理、网络安全、信息收集、输入重建等。
晓兵
2024/05/03
6400
使用 DPDK 和 GPUdev 在 GPUs上增强内联数据包处理
编写高效代码--内存篇
在近期线上故障排查过程中,我发现代码中仍在使用一些libc库函数,诸如malloc()内存分配、memset()内存清零及htonl()、ntohl()高低字节序转换等,这些函数在性能上存在优化空间。鉴于此,本文将借鉴DPDK《高效编码指南》中的相关内容,探讨VPP框架下更为高效的实现策略,以替换上述传统函数,提升系统性能。本节主要介绍在 DPDK&VPP 环境中开发应用程序时的一些关键内存注意事项。
dpdk-vpp源码解读
2024/05/14
4950
编写高效代码--内存篇
C/C++ 性能优化背后的方法论:TMAM
开发过程中我们多少都会关注服务的性能,然而性能优化是相对比较困难,往往需要多轮优化、测试,属于费时费力,有时候还未必有好的效果。但是如果有较好的性能优化方法指导、工具辅助分析可以帮助我们快速发现性能瓶颈所在,针对性地进行优化,可以事半功倍。
2020labs小助手
2021/03/17
2.7K0
DPDK-vpp 一次mbuf地址被踩的定位思路
本文转载来源于个人博客--https://blog.csdn.net/sjin_1314
dpdk-vpp源码解读
2023/01/04
8840
DPDK-vpp 一次mbuf地址被踩的定位思路
定位并行应用程序中的可伸缩性问题(最透彻一篇)
本文由西邮陈莉君教授研一学生梁金荣、戴君毅、马明慧翻译,宋宝华老师指导和审核。译者梁金荣、戴君毅、马明慧同学热爱开源,践行开放、自由和分享。
Linux阅码场
2020/04/08
9810
C++ 如何进行性能优化?
在 C++ 中进行性能优化是一个多方面的过程,涉及代码编写、编译器优化、算法选择和数据结构设计等多个方面。以下是一些常见的性能优化技巧:
代码小李
2025/01/27
1550
全用户态网络开发套件 F-Stack 架构分析
F-Stack
2017/06/12
12.1K3
全用户态网络开发套件 F-Stack 架构分析
【重识云原生】第四章云网络4.9.3.2节——DPDK原理详解
        相对传统的基于内核的网络数据处理,dpdk 对从内核层到用户层的网络数据流程进行了重大突破,我们先看看传统的数据流程和 dpdk 中的网络流程有什么不同。
江中散人_Jun
2022/09/08
2.6K0
【重识云原生】第四章云网络4.9.3.2节——DPDK原理详解
《深入浅出DPDK》&《DPDK应用基础》读书笔记
本文主要介绍了我在阅读《深入浅出DPDK》,《DPDK应用基础》这两本书中所划下的知识点
没有故事的陈师傅
2020/11/19
4.6K0
《深入浅出DPDK》&《DPDK应用基础》读书笔记
从 10 Gb 到 40 Gb,从百万级到千万级转发,打造高性能 TGW
腾讯架构师
2017/09/08
6.6K1
从 10 Gb 到 40 Gb,从百万级到千万级转发,打造高性能 TGW
vpp IPsec with DPDK Cryptodev have buffer resource leak.
此刻是否已经准备下班或者已经在下班的路上,首先提前祝大家五一快乐,北京疫情正处于关键阶段,各位出行注意防护。
dpdk-vpp源码解读
2023/01/04
1.3K0
vpp IPsec with DPDK Cryptodev have  buffer resource leak.
F-Stack 全用户态 (Kernel Bypass) 服务开发套件
本文介绍了 F-Stack 框架,它是一个基于 FreeBSD 内核的用户态协议栈实现,解决了传统内核协议栈在高性能、可扩展、兼容性、功能完备等方面的问题。F-Stack 提供了丰富的功能,包括零拷贝、无锁队列、内存池、红黑树等,支持多种调度算法,并提供了易用的接口。在性能测试中,F-Stack 的表现优异,最高达到了 2000 万 QPS,并支持多种网络协议,包括 HTTP、TCP、UDP、IPX 等。同时,F-Stack 也提供了丰富的开发文档和示例代码,方便开发者进行二次开发和功能扩展。
F-Stack
2017/06/02
23.1K6
F-Stack 全用户态 (Kernel Bypass) 服务开发套件
【重识云原生】第四章云网络4.9.3.1节——DPDK技术综述
        数据平面开发套件(DPDK [1]  ,Data Plane Development Kit)是由6WIND,Intel等多家公司开发,主要基于Linux系统运行,用于快速数据包处理的函数库与驱动集合,可以极大提高数据处理性能和吞吐量,提高数据平面应用程序的工作效率。
江中散人_Jun
2022/09/08
1.7K0
【重识云原生】第四章云网络4.9.3.1节——DPDK技术综述
推荐阅读
相关推荐
高性能网关设备及服务实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验