【DPDK】【CPU usage】DPDK应用如何得到当前系统的负载
【前言】
使用DPDK开发的朋友应该都了解使用dpdk的fwd线程的工作模式是polling模式,即100%轮询的方式去加速网络IO,这样我们在操作系统层面上来观察目标processer会发现usage一直为100%,但是这真的是系统的真实负载么?很显然并不是,本文给出一种方法来计算dpdk的fwd线程的真实负载的方法。
【场景】
使用DPDK头痛的一点就是DPDK的fwd线程工作在polling模式,会直接消耗一整个processer的计算资源,有的时候为了性能考虑,往往还会给当前processer设置isolcpus,将当前processer从内核的CFS调度器中“剥离”出来,防止有其他的task被“不长眼”的CFS调度器调度到和fwd线程同一个processer上,出现context switch,引起性能下降。
而工作在polling模式的fwd线程会出现非常蛋疼的一点就是面临“无法有效的感知当前processer的压力”的问题。查看操作系统的相关信息,会发现这个processer的usage一直处于100%,但是真实情况真的是这样么?并不是,在流量处于低谷的时候,这个processer往往会出现空转的情况,就是调用dpdk的api收包函数调100次,次次收包个数都是0,因为根本就没有流量,所以需要一种新的方法来计算使用dpdk fwd线程的负载情况。
额外多说一点,为了防止fwd线程出现空转,目前有不同种方法来“尽量”解决这种空转问题,主流的通常有两种:
- 利用sleep函数,简单粗暴,结合内核的NAPI策略,设定一个期望收包个数值,当实际收包个数小于这个数值就判断当前流量不大,sleep一下。
- 利用dpdk的rsc中断来解决,由于uio驱动只有一个中断号,因此这种方法在uio驱动基本没法用,只能在vfio场景下用。
当然怎么防止dpdk fwd线程出现空转的解决方法不是这篇文章想讨论的主题,我后续会写我个人的解决方案,本篇文章更多的会聚焦在如何估算负载情况。
【分析】
这里首先说明一下,这个方法里面有一部分是来自于dpdk社区的一篇文章,由intel专家ilia所写,这里是文章原文地址,本文中会有不少部分来自于这篇文章原文,但是本篇文章在实际应用中仍然是有些地方需要注意的。
https://software.intel.com/en-us/vtune-cookbook-core-utilization-in-dpdk-apps
接下来我会结合实际应用和ilia的文章来阐述怎么“估算”dpdk fwd线程的负载情况。
先直接说结论:
在不同的流量压力下,dpdk fwd线程对某个网卡队列的收包行为实际上是存在一定的分布的
这句话怎么理解呢?实际上这句话就是intel专家ilia那篇文章的主要思想。
这句话完整的解释是这样的:
在不同的流量压力下,dpdk fwd线程对某个网卡的某条队列进行收包操作,单位时间内的收包次数中,收到数据包的个数存在一定的分布
举个例子:
我在10s内,执行了1000次收包操作,在满载的流量压力下,1000次收包可能次次收包都能收上来32个数据包;在50%压力下,我可能只有300次收包是一次调用收上来32个包;在10%的压力下,我可能只有不到100次的收包是一次性收上来32个包。
如果能明白这个例子,就能明白前面所说的结论,关于这个结论可以直接看【测试结果】一章,观察测试结果是否符合结论。
以收包个数为0的次数为基准,那么可以推导出一个公式:
【测试结果】
【结论】
【另一个问题:DPDK应用怎么“预见”即将可能发生的丢包】
原文地址:https://www.cnblogs.com/jungle1996/p/12172491.html
- 用shape画内圆外方,形成一个圆形头像
- 在Go中对gRPC+ProtoBuf与Http+Json进行基准测试
- Achartengine.jar绘制动态图形一 --饼图
- 工具| 关于Python线程和队列使用的小思考
- Java中list<Object[]>、list<Student>、list<Map<String,String>>排序
- Java-单例模式详解(图文并茂,简单易懂)
- Fragment生命周期及实现点击导航图片切换fragment,Demo
- 《GO IN ACTION》读后记录:GO的并发与并行
- SharedPreferences 存List集合,模拟数据库,随时存取
- Servlet与Jsp的结合使用实现信息管理系统一
- Mac下nvm管理node.js版本问题
- 自定义tab吸顶效果一(原理)
- OpenGL ES学习001---绘制三角形
- Android之MaterialDesign应用技术2-仿支付宝上滑搜索框缓慢消失
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- String - 316. Remove Duplicate Letters
- String - 38. Count and Say
- String - 161. One Edit Distance
- String - 6. ZigZag Conversion
- String - 179. Largest Number
- 利用Github Pages实现“服务CNAME”功能
- String - 49. Group Anagrams
- Flutter包大小治理上的探索与实践
- String - 242. Valid Anagram
- String - 290. Word Pattern
- String - 205. Isomorphic Strings
- String - 345. Reverse Vowels of a String
- String - 186. Reverse Words in a String II
- String - 151. Reverse Words in a String
- String - 344. Reverse String