一、故障背景
某运营商城域网核心交换机采用纯软件转发架构。
主要业务:
- IPv4/IPv6转发
- VXLAN Gateway
- EVPN接入
- ACL
- QoS
硬件平台:
| CPU | Intel Xeon Gold 6430 |
| 网卡 | Intel E810 |
| DPDK | 23.11 |
| PMD | 32核 |
| RX Queue | 32 |
| TX Queue | 32 |
上线压测:
98Mpps
稳定运行。
半年后扩容。
新增:
Telemetry
Mirror
Flow Statistics
随后出现:
98Mpps
↓
85Mpps
↓
72Mpps
CPU:
100%
始终不变。
二、第一轮排查
检查:
rte_eth_stats_get()
结果:
imissed=0
ierrors=0
rx_nombuf=0
正常。
RSS:
32 Queue均衡
正常。
ACL:
Lookup Cycle稳定
正常。
FIB:
DIR24_8稳定
正常。
问题无法解释。
三、一个奇怪现象
继续分析。
发现:
RX PMD统计:
每轮收到:
32包
非常稳定。
但:
Worker线程:
平均处理:
7~11包
TX线程:
平均发送:
6~8包
出现明显差异。
四、DPDK最核心的设计思想
很多开发者认为:
DPDK优势来自:
零拷贝
轮询
无锁
实际上还有一个更重要的思想:
Batch Processing
DPDK真正优化对象:
不是:
Packet
而是:
Packet Batch
例如:
rte_eth_rx_burst()
一次返回:
32个包
目的是:
把大量固定成本:
Doorbell
PCIe访问
Cache同步
函数调用
分摊掉。
五、Burst为什么重要
假设:
处理一个包:
解析:
50 cycles
转发:
50 cycles
固定成本:
Loop
Ring
Cache同步
200 cycles
单包:
300 cycles
32包:
(200 + 32×100)
/32
≈106 cycles
效率提升接近3倍。
六、交换机中的真实流水线
实际系统:
RX PMD
↓
Dispatch Ring
↓
Worker
↓
TX Ring
↓
TX PMD
如下图所示:





七、问题开始出现
扩容后新增:
flow_stat_update();
开发人员加入:
if(flow_need_update)
{
flush_stat();
}
结果:
Worker频繁提前退出。
原来:
process 32 packets
后来:
process 8 packets
flush
process 10 packets
flush
Burst被切碎。
八、第一个放大效应
RX:
32包
Worker:
8包
TX:
6包
形成:
32
↓
8
↓
6
整个流水线效率开始下降。
九、第二个放大效应
Ring缓存设计:
rte_ring
最优状态:
批量入队
批量出队
例如:
rte_ring_enqueue_bulk()
此时:
CAS次数
最少
但:
Burst变小后:
bulk
↓
single
Ring开销激增。
十、第三个放大效应
Cache预取失效。
DPDK典型代码:
prefetch(pkt[i+4]);
process(pkt[i]);
要求:
连续包流
Burst被切碎后:
Prefetch距离不足
CPU等待:
Memory Fetch
时间增加。
十一、第四个放大效应
TX Doorbell问题。
正常:
32包
一次Doorbell
异常:
6包
一次Doorbell
Doorbell次数:
增长:
5倍以上
PCIe事务显著增加。
十二、现场证据
统计:
rte_eth_tx_burst()
平均发送:
正常:
28~32
异常:
5~8
Ring统计:
enqueue bulk
下降:
87%
变成:
single enqueue
十三、Perf分析
统计:
perf stat
发现:
Instructions
变化不大
但:
Cycles/Packet
从:
128
增加到:
223
增长:
74%
十四、真正根因
完整链路:
Flow Stat Flush
↓
Burst切碎
↓
Ring效率下降
↓
Prefetch失效
↓
Doorbell增加
↓
Cycles/Packet增加
↓
PPS下降
十五、优化方案
方案一
严格统一Burst大小。
统一:
#define BURST_SIZE 32
所有模块:
RX
Worker
TX
保持一致。
方案二
统计异步化。
原来:
Packet Path
↓
Update Stat
改:
Packet Path
↓
Per Core Cache
↓
Timer Flush
方案三
Ring批量接口
统一:
rte_ring_enqueue_bulk()
rte_ring_dequeue_bulk()
避免:
single enqueue
方案四
增加Pipeline Buffer
Worker内部:
Local Cache
累计:
32包
再发送。
十六、优化结果
优化前:
| PPS | 72M |
| Avg Burst | 7 |
| Cycles/Packet | 223 |
| RTT P99 | 4.9ms |
优化后:
| PPS | 97M |
| Avg Burst | 31 |
| Cycles/Packet | 131 |
| RTT P99 | 0.8ms |
核心知识点总结
知识点1
DPDK优化对象不是单个Packet。
而是:
Packet Batch
知识点2
Burst大小决定流水线效率。
知识点3
RX Burst、Worker Burst、TX Burst必须匹配。
知识点4
Burst变小会同时影响:
Ring
Prefetch
Doorbell
Cache
多个系统。
知识点5
CPU 100%不代表处理效率最高。
真正指标是:
Cycles Per Packet
知识点6
很多性能问题并非算力不足。
而是:
流水线失配
知识点7
高性能交换机设计中:
保持大Burst连续流动
往往比优化某个函数快几条指令更重要。
这类问题在真实交换机项目中非常隐蔽,因为所有PMD线程都会持续100%运行,所有常规指标也都正常,但系统吞吐会明显下降。本质上,这是DPDK批处理模型被破坏后导致的系统级效率损失,属于比ACL、FIB、RSS更偏架构层面的性能问题。





