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

news/2024/5/15 11:43:27/文章来源:https://blog.csdn.net/lingshengxiyou/article/details/128037217

产生性能瓶颈有多方面的原因,包括硬件(自身能力限制或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。考虑如下两个结构体:
 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成员。

 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进行预取操作,如下是预取数据包的示例代码:

 /* 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名称的目录,里面存放的是收集的结果

 ./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时间了。

(免费订阅,永久学习)学习地址: Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂

更多DPDK相关学习资料有需要的可以自行报名学习,免费订阅,永久学习,或点击这里加qun免费
领取,关注我持续更新哦! !   

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

总结

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

原文链接:https://cloud.tencent.com/developer/article/1394706

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_36725.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[附源码]java毕业设计疫情期间回乡人员管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

「运维有小邓」如何更有效的避免密码攻击

在这表文章中&#xff0c;让我们一起了解密码在网络安全中的重要性&#xff0c;在我们的日常工作中&#xff0c;密码泄露事件是常发生的&#xff0c; 那今天我们就一起了解ManageEngine ADSelfService Plus 是如何强化您的密码并加强您的企业AD域安全性的。 运维有小邓 2022 年…

ArcGIS绘制地球

下面这个图是非常不错的&#xff0c;截取自论文的一张图&#xff1a; 学了十几年地理学&#xff0c;最初的兴趣恐怕还是小时候常常摆弄的地球仪&#xff1b;现在终于有机会尝试地球仪风格制作了。 虽然迟到了十几年&#xff0c;不过今天还是有机会“复现”小时候的地球仪。 先…

计算机网络协议------从入门到深化

计算机网络通信 什么是通信协议 简单来说&#xff0c;通信协议就是计算机之间通过网络实现通信时事先达成 的一种“约定”&#xff1b;这种“约定”使那些由不同厂商的设备&#xff0c;不同CPU及不 同操作系统组成的计算机之间&#xff0c;只要遵循相同的协议就可以实现通 信。…

栈和队列及其多种接口实现-c语言

今天我们来完成栈和队列&#xff0c;首先我们要明白什么是栈&#xff0c;什么是队列。 目录 栈的选择 栈的结构 栈的初始化 栈的销毁 入栈 出栈 返回栈顶元素 计算数据个数 判断是否为空 队列的选择 队列的结构 入队列 出队列 判断是否为空 取队头元素 取队尾…

适用更多会议场景,华为云会议的分组讨论功能来了!

适用更多会议场景&#xff0c;华为云会议的分组讨论功能来了&#xff01; 如今&#xff0c;线上沟通成为常态&#xff0c;线上会议更是成为工作推进过程中不可缺少的环节。但在一些场景中&#xff0c;例如在跨部门协调&#xff0c;沙龙研讨&#xff0c;教育培训或者招聘面试时&…

使用docker-compose部署达梦DEM管理工具,mac m1系列适用

之前搭建了mac m1下基于docker的达梦库&#xff08;地址&#xff09;&#xff0c;但是没有一个好用的管理端。 用过DBeaver&#xff0c;可以使用自定jar创建dm链接&#xff0c;只做简单查询还行&#xff0c;要是用到一些修改、大文本查看、配置修改等高级点的功能就不行了。 …

小啊呜产品读书笔记001:《邱岳的产品手记-12》第22讲 产品经理的图文基本功(上):产品文档 23讲产品经理的图文基本功(下):产品图例

小啊呜产品读书笔记001&#xff1a;《邱岳的产品手记-12》第22讲 产品经理的图文基本功&#xff08;上&#xff09;&#xff1a;产品文档 & 23讲产品经理的图文基本功&#xff08;下&#xff09;&#xff1a;产品图例一、今日阅读计划二、泛读&知识摘录1、第22讲 产品经…

m在ISE平台下使用verilog开发基于FPGA的GMSK调制器

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 高斯最小频移键控&#xff08;Gaussian Filtered Minimum Shift Keying&#xff09;&#xff0c;这是GSM系统采用的调制方式。数字调制解调技术是数字蜂窝移动通信系统空中接口的重要组成…

ES6 入门教程 26 编程风格 26.1 块级作用域 26.2 字符串 26.3 解构赋值

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程26 编程风格26.1 块级作用域26.1.1 **let 取代 var**26.1.2 **全局常量和线程安全**26.2 字符串26.3 解构赋值26 编程风格 …

【算法基础】P问题、NP问题、NP-Hard问题、NP-Complete问题

P问题、NP问题、NP-Hard问题、NP-Complete问题前提1. 时间复杂度&#xff1a;2. 约化(Reducibility)P问题NP问题NPHard问题NP-Complete问题其它&#xff1a;前提 1. 时间复杂度&#xff1a; 2. 约化(Reducibility) 如果能找到一个变化法则&#xff0c;对任意一个A程序的输入&…

TOWER 成就徽章 NFT 系列介绍——TOWER 生态系统的第一个灵魂通证(SBT)

2022 年 7 月&#xff0c;团队推出了成就徽章 NFT 系列&#xff0c;记录每个成员在 TOWER 生态系统中的努力。这是第一个不可转让的灵魂 NFT 系列&#xff08;SBT&#xff09;&#xff0c;代表了每个玩家的独特身份。 关于灵魂通证&#xff08;SBT&#xff09; 以太坊联合创始人…

linux的重定向与xshell原理

文章目录一、重定向1.输出重定向&#xff1a;>1.写入指定文件2. 覆盖写2.追加重定向 &#xff1a;>>3.输出重定向&#xff1a;<1.键盘显示2.文件显示4.重定向的一些认知误区1. test.c只显示错误的2. msg.c只显示正确的3.分析4.显示出正确的二 、xshell命令及原理1.…

2023年第三届智能制造与自动化前沿国际会议(CFIMA 2023)

2023年第三届智能制造与自动化前沿国际会议(CFIMA 2023) 重要信息 会议网址&#xff1a;www.cfima.org 会议时间&#xff1a;2023年6月9-11日 召开地点&#xff1a;中国大理 截稿时间&#xff1a;2023年4月20日 录用通知&#xff1a;投稿后2周内 收录检索&#xff1a;EI,…

关于SD-WAN的十问十答(最强攻略戳这里)

1. WAN和SD-WAN之间的区别&#xff1f; 从底层来看&#xff0c;相较基于硬件物理设施的WAN&#xff0c;SD-WAN是一种覆盖现有网络的软件技术&#xff0c;是部署在物理基础设施下层的流量管理网络。 和常规WAN相比&#xff0c;SD-WAN具有虚拟WAN体系结构和软件驱动技术&#xff…

国内优秀的多用户商城系统盘点(2022年整理)

电商战略时代&#xff0c;越来越多的企业或商家选择将消费者引入自己建设的独立商城&#xff0c;如零食行业的良品铺子、三只松鼠&#xff0c;从而打造属于自己的IP形象。此时&#xff0c;挑选一款优秀的商城源码是企业的不二之选&#xff0c;既降低了电商从业者和创业者的入门…

hive表加载csv格式数据或者json格式数据

先说简单的使用 CREATE TABLE cc_test_serde( id string COMMENT from deserializer, name string COMMENT from deserializer) ROW FORMAT SERDE org.apache.hadoop.hive.serde2.JsonSerDe STORED AS INPUTFORMAT org.apache.hadoop.mapred.TextInputFormat OUTPUTFO…

决策树-相关作业

1. 请使用泰勒展开推导gini不纯度公式&#xff1b; 2. 请说明树的剪枝怎么实现&#xff1b; ●预剪枝&#xff08;pre-pruning&#xff09;通过替换决策树生成算法中的停止准则。&#xff08;例如&#xff0c;最大树深度或信息增益大于某一阈值&#xff09;来实现树的简化。预…

Mybatis-plus通过exists判断记录是否存在

Mybatis-plus通过exists判断记录是否存在一、Controller二、Service三、效果一、Controller GetMapping("/queryNewProductExists")public Boolean queryNewProductExists(RequestParam("name") String name) {return opProductService.queryNewProductExi…

基于sklearn的集成学习实战

集成学习投票法与bagging 投票法 sklearn提供了VotingRegressor和VotingClassifier两个投票方法。使用模型需要提供一个模型的列表&#xff0c;列表中每个模型采用tuple的结构表示&#xff0c;第一个元素代表名称&#xff0c;第二个元素代表模型&#xff0c;需要保证每个模型…