DPDK基础入门(七):网卡性能优化

server/2024/12/22 9:06:09/

DPDK的轮询模式

运行在操作系统内核态的网卡驱动程序基本都是基于异步中断处理模式,而DPDK采用了轮询或者轮询混杂中断的模式来进行收包和发包。

任何包进入到网卡,网卡硬件会进行必要的检查、计算、解析和过滤等,最终包会进入物理端口的某一个队列。物理端口上的每一个收包队列,都会有一个对应的由收包描述符组成的软件队列来进行硬件和软件的交互,以达到收包的目的。

轮询模式

DPDK的轮询驱动程序负责初始化好每一个收包描述符,其中就包含把包缓冲内存块的物理地址填充到收包描述符对应的位置,以及把对应的收包成功标志复位。然后驱动程序修改相应的队列管理寄存器来通知网卡硬件队列里面的哪些位置的描述符是可以有硬件把收到的包填充进来的。

网卡硬件会把收到的包填充到对应的收包描述符表示的缓冲内存块里面,同时把必要的信息填充到收包描述符里面,其中最重要的就是标记好收包成功标志。当一个收包描述符所代表的缓冲内存块大小不够存放一个完整的包时,这时候就可能需要两个甚至多个收包描述符来处理一个包。

每一个收包队列,DPDK都会有一个对应的软件线程负责轮询里面的收包描述符的收包成功的标志。一旦发现某一个收包描述符的收包成功标志被硬件置位了,就意味着有一个包已经进入到网卡,并且网卡已经存储到描述符对应的缓冲内存块里面,这时候驱动程序会解析相应的收包描述符,提取各种有用的信息,然后填充对应的缓冲内存块头部。然后把收包缓冲内存块存放到收包函数提供的数组里面,同时分配好一个新的缓冲内存块给这个描述符,以便下一次收包。

每一个发包队列,DPDK都会有一个对应的软件线程负责设置需要发送出去的包,DPDK的驱动程序负责提取发包缓冲内存块的有效信息,例如包长、地址、校验和信息、VLAN配置信息等。DPDK的轮询驱动程序根据内存缓存块中的包的内容来负责初始化好每一个发包描述符,驱动程序会把每个包翻译成为一个或者多个发包描述符里能够理解的内容,然后写入发包描述符。

发包的轮询就是轮询发包结束的硬件标志位,当驱动程序发现写回标志,意味着包已经发送完成,就释放对应的发包描述符和对应的内存缓冲块,这时候就全部完成了包的发送过程。

混和中断轮询模式

由于实际网络应用中可能存在的潮汐效应,在某些时间段网络数据流量可能很低,甚至完全没有需要处理的包,这样就会出现在高速端口下低负荷运行的场景,而完全轮询的方式会让处理器一直全速运行,明显浪费处理能力和消耗资源。

因此在DPDK R2.1和R2.2陆续添加了收包中断与轮询的混合模式的支持。例子程序l3fwd-power(examples\l3fwd-power\main.c),使用了DPDK支持的中断加轮询的混合模式。应用程序开始就是轮询收包,这时候收包中断是关闭的。但是当连续多次收到的包的个数为零的时候,应用程序定义了一个简单的策略来决定是否以及什么时候让对应的收包线程进入休眠模式,并且在休眠之前使能收包中断。休眠之后对应的核的运算能力就被释放出来。当后续有任何包收到的时候,会产生一个收包中断,并且最终唤醒对应的应用程序收包线程。线程被唤醒后,就会关闭收包中断,再次轮询收包。

static int
sleep_until_rx_interrupt(int num, int lcore)
{/** we want to track when we are woken up by traffic so that we can go* back to sleep again without log spamming. Avoid cache line sharing* to prevent threads stepping on each others' toes.*/static alignas(RTE_CACHE_LINE_SIZE) struct {bool wakeup;} status[RTE_MAX_LCORE];struct rte_epoll_event event[num];int n, i;uint16_t port_id;uint16_t queue_id;void *data;if (status[lcore].wakeup) {RTE_LOG(INFO, L3FWD_POWER,"lcore %u sleeps until interrupt triggers\n",rte_lcore_id());}n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, 10);for (i = 0; i < n; i++) {data = event[i].epdata.data;port_id = ((uintptr_t)data) >> (sizeof(uint16_t) * CHAR_BIT);queue_id = ((uintptr_t)data) &RTE_LEN2MASK((sizeof(uint16_t) * CHAR_BIT), uint16_t);RTE_LOG(INFO, L3FWD_POWER,"lcore %u is waked up from rx interrupt on"" port %d queue %d\n",rte_lcore_id(), port_id, queue_id);}status[lcore].wakeup = n != 0;return 0;
}

比如以上的例子,sleep_until_rx_interrupt 函数用于让逻辑核心在等待网络流量中断时进入休眠状态。它在被唤醒后记录唤醒事件的信息,并更新核心的状态。

在这里插入图片描述

网卡I/O性能优化

Burst收发包

Burst收发包就是DPDK的优化模式,它把收发包复杂的处理过程进行分解,打散成不同的相对较小的处理阶段,把相邻的数据访问、相似的数据运算集中处理。这样就能尽可能减少对内存或者低一级的处理器缓存的访问次数,用更少的访问次数来完成更多次收发包运算所需要数据的读或者写

如果每次只收一个包,然后处理。那么在收一个包的时候发生内存访问或者低一级的处理器缓存访问的时候,往往会把临近的数据一并同步到处理器缓存中,因为处理器缓存更新都是按固定cache line(例如64字节)加载的。到中间计算的时候为了空出处理器缓存,把前面读取的数据又废弃了,下一次需要用到临近数据的时候又需要重新访问低一级处理器缓存,甚至是直接内存访问。

如果每次只发送一个包,在内存访问或者处理器缓存同步的时候,同样是按照cache line大小加载或同步数据,一样会有一些数据同步了却不需要使用,这就造成了内存访问和处理器缓存同步能力的浪费。

CPU指令乱序多发

在时延相对固定的情况下,要提升指令执行的整体性能,需要利用有些指令的多发能力。利用CPU指令乱序多发的能力,掩藏指令延迟,批量处理无数据前后依赖关系的独立事务。

指令延迟指的是在执行CPU指令时,某些指令可能会因依赖于前面的指令结果而产生的延迟。这个延迟通常发生在指令还未完成时,后续的指令无法执行或需要等待。利用CPU的乱序执行能力,CPU可以在遇到这种延迟时,继续执行其他指令,而不是等待前面的指令完成。这样,处理器可以“掩藏”或减少指令延迟的影响,提高整体处理效率。

Intel SIMD指令

SIMD,单指令多数据,允许在一个指令周期内同时对多个数据元素进行操作。常见的SIMD指令集包括SSE(Streaming SIMD Extensions)、AVX(Advanced Vector Extensions)和AVX-512等。

例如,一个SIMD指令可以在一个操作中对多个数据点进行加法、乘法等操作,而不是逐个处理每个数据点。

DPDK参数

收包队列长度:DPDK很多示例程序里面默认的收包队列长度是128,这就是表示为每一个收包队列都分配128个收包描述符,这是一个适应大多数场景的经验值。但是在某些更高速率的网卡收包的情况下,128就可能不够了,或者在某些场景下发现丢包现象比较容易的时候,就需要考虑使用更长的收包队列,例如可以使用512或者1024。

发包队列长度:DPDK的示例程序里面默认的发包队列长度使用的是512,这就表示为每一个发包队列都分配512个发包描述符,这是一个适用大部分场合的经验值。当处理更高速率的网卡设备时,或者发现有丢包的时候,就应该考虑更长的发包队列,例如1024。

收包队列可释放描述符数量阈值(rx_free_thresh):DPDK驱动程序并没有每次收包都更新收包队列尾部索引寄存器,而是在可释放的收包描述符数量达到一个阈值(rx_free_thresh)的时候才真正更新收包队列尾部索引寄存器。这个可释放收包描述符数量阈值在驱动程序里面的默认值一般都是32,在示例程序里面,有的会设置成用户可配参数,可能设置成不同的默认值,例如64或者其他。设置合适的可释放描述符数量阈值,可以减少没有必要的过多的收包队列尾部索引寄存器的访问,改善收包的性能。

发包队列发送结果报告阈值(tx_rs_thresh):这个阈值的存在允许软件在配置发包描述符的同时设定一个回写标记,只有设置了回写标记的发包描述符硬件才会在发包完成后产生写回的动作,并且这个回写标记是设置在一定间隔(阈值)的发包描述符上。这个机制可以减少不必要的回写的次数,从而能够改善性能。

发包描述符释放阈值(tx_free_thresh):在DPDK驱动程序里面,默认值是32,用户可能需要根据实际使用的队列长度来调整。发包描述符释放阈值设置得过大,则可能描述符释放的动作很频繁发生,影响性能;发包描述符释放阈值设置过小,则可能每一次集中释放描述符的时候耗时较多,来不及提供新的可用的发包描述符给发包函数使用,甚至造成丢包。


http://www.ppmy.cn/server/114289.html

相关文章

PostgreSQL-05-入门篇-数据分组

文章目录 1. GROUP BY 分组简介示例1) 不使用聚合函数的 GROUP BY2) 使用 SUM() 函数的 GROUP BY3) 结合 JOIN 子句的 GROUP BY4) 使用 COUNT() 函数的 GROUP BY5) 多列 GROUP BY6) 使用日期列的 GROUP BY 2. HAVING 子句简介HAVING 对比 WHEREPostgreSQL HAVING 子句示例1) 使…

Ignis公链探索生态建设新范式:产业区块链与GameFi双轨驱动

Ignis公链凭借其独特的技术架构&#xff0c;选择了产业区块链与GameFi这两个赛道作为生态建设的双轮驱动&#xff0c;逐步形成了一个多元化的Web3生态系统。 一、产业区块链的革新&#xff1a;Vessel Chain的成功案例 在产业区块链领域&#xff0c;Ignis公链通过推出Vessel Ch…

学习node.js十三,文件的上传于下载

文件上传 文件上传的方案&#xff1a; 大文件上传&#xff1a;将大文件切分成较小的片段&#xff08;通常称为分片或块&#xff09;&#xff0c;然后逐个上传这些分片。这种方法可以提高上传的稳定性&#xff0c;因为如果某个分片上传失败&#xff0c;只需要重新上传该分片而…

基于SpringBoot的高校宿舍管理系统+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

springboot个性化大学生线上聊天交友系统

基于springbootvue实现的个性化大学生线上聊天交友系统 &#xff08;源码L文ppt&#xff09;4-017 4系统设计 4.1 软件功能模块设计 个性化大学生线上聊天交友分为两个模块&#xff0c;分别是管理员功能模块和用户功能模块。主要功能模块包括&#xff…

KUKA中级学习4:修改软件中机器人名字,纠正示教器时间,下载备份文件进示教器

这里写目录标题 一、修改机器人名字1.1、程序安装下载二、示教器时间修改2.1、时间修改&#xff0c;示教器全英文显示三、下载备份文件 一、修改机器人名字 1.1、程序安装下载 选下面这个 二、示教器时间修改 2.1、时间修改&#xff0c;示教器全英文显示 三、下载备份文件 …

深入解读Docker核心网络管理:架构、模式与通信机制

在容器化技术中&#xff0c;网络管理是影响容器通信和应用部署的重要组成部分。Docker不仅简化了应用的部署过程&#xff0c;还提供了强大的网络管理功能&#xff0c;确保容器之间以及容器与外部系统的网络通信能够高效、稳定地进行。 本文将深入解读Docker的核心网络管理原理…

Hfinger:一款针对恶意软件HTTP请求的指纹识别工具

关于Hfinger Hfinger是一款功能强大的HTTP请求指纹识别工具&#xff0c;该工具使用纯Python开发&#xff0c;基于Tshark实现其功能&#xff0c;可以帮助广大研究人员对恶意软件的 HTTP 请求进行指纹识别。 该工具的主要目标是提供恶意软件请求的唯一表示&#xff08;指纹&…