为什么我的 DPDK 程序吞吐很高,但时延却越来越大?一次排查让我彻底理解 burst
做 DPDK 开发时,我一开始最关注的就是:吞吐。
例如:
- PPS
- Gbps
- 丢包率
于是:程序优化到:20 Mpps
看起来非常漂亮。
但真实业务上线后,却出现一个非常诡异的问题:
现象
吞吐没问题。没有丢包。
但是:时延越来越高。
尤其在高流量时:
- ping 抖动
- RTT 增加
- 小包响应变慢
- tail latency 非常严重
最奇怪的是:系统没有任何明显错误。
最后一次真实排查,让我真正理解了:DPDK 中 burst 的本质。
一、问题现场
程序结构:
RX core
收包。
worker core
处理业务。
TX core
发包。
代码非常典型:
nb_rx = rte_eth_rx_burst(port, qid, pkts, 32);
处理完成后:
rte_eth_tx_burst(port, qid, pkts, nb_rx);
压测结果
吞吐:
18~20 Mpps
非常稳定。
但:业务 RTT:
50us -> 500us -> 2ms
逐渐恶化。
二、第一反应:是不是 CPU 不够
查看:
top -H
发现:
CPU 甚至没满。
很多核:
60%
70%
说明:
不是算力瓶颈。
三、第二反应:是不是 ring 堵塞
查看:DPDK Ring 长度:
rte_ring_count()
发现:确实偶尔升高。
但没有完全打满。
不像死锁。
四、真正突破口:观察 packet batch
后来打印:
每次 burst 的实际 packet 数量
发现:大量情况:
32 packets
即:burst 总是满。
这里开始暴露问题。
五、什么是 burst
在 DPDK 中:
核心 API:
rte_eth_rx_burst()
并不是:“收一个包”。
而是:批量收包。
例如:
32
64
128
一次处理多个包。
六、为什么 DPDK 喜欢 batch
因为 batch 能显著提升吞吐。
原因包括:
1. 减少函数调用
一次处理 32 个。比:32 次处理 1 个。
效率高得多。
2. 提高 cache locality
连续 mbuf 更容易命中 cache。
3. 减少 descriptor 更新
NIC 可以批量推进 queue。
4. 提高 SIMD 效率
部分 PMD 会向量化处理。
七、为什么 burst 会导致时延升高
这是核心问题。
假设:当前 queue 中:
只有:
1 packet
但程序:
希望凑够:
32 packet
才一起处理。
那么:第一个包必须等待后续包到来。
即:batching delay 批处理延迟。
八、这本质上是“吞吐优先”
burst 的设计哲学:不是最低时延。
而是:最大吞吐。
因为:批量处理更高效。
九、一个非常典型的误区
很多人以为:
burst = 64
一定比:
burst = 16
更好。
其实不一定。
十、吞吐和时延通常是对立的
这是高性能系统中的经典 tradeoff。
大 burst
优点:
- 吞吐高
- cache 友好
- CPU 更省
缺点:
- 等待时间增加
- tail latency 上升
小 burst
优点:
- 响应更快
- latency 更低
缺点:
- PPS 下降
- CPU 开销增加
十一、真实现场中的问题
当时程序:
burst = 64
并且:worker 也采用 batch。
于是:形成:
RX batch
↓
worker batch
↓
TX batch
三级累积。
十二、结果
每一级都在:“等更多包”。
最终:单包排队时间显著增加。
十三、这就是 tail latency 爆炸的根本原因
平均吞吐很好。
但:最后几个包等待极长。
于是:P99 latency 飙升。
十四、进一步理解 pipeline
DPDK 程序本质上是:packet pipeline
结构:



RX -> ring -> worker -> TX
每一级:都可能积压。
十五、另一个隐藏问题:backpressure
如果 downstream 较慢:burst 会导致:queue rapidly accumulate。
即:背压。
十六、为什么 CPU 不高,但 latency 很高
因为:系统不是算力不足。
而是:packet 正在排队等待 batch。
CPU 甚至还有空闲。但包已经在 pipeline 中堆积。
十七、如何验证
我后来增加:timestamp。
例如:
rx_ts
worker_ts
tx_ts
结果发现:大部分时间消耗并不是:业务处理。
而是:
waiting in queue
十八、如何优化
做了几个关键调整。
1. 减小 burst
从:
64
调整为:
16
2. 小包流量优先
不同流量采用不同 batch 策略。
3. worker 及时 flush
不再无限等待:batch 满。
4. ring 设置 watermark
防止积压。
十九、优化结果
优化前:
| 指标 | 数值 |
|---|---|
| Throughput | 20 Mpps |
| P99 latency | 2.3 ms |
优化后:
| 指标 | 数值 |
|---|---|
| Throughput | 17 Mpps |
| P99 latency | 110 us |
吞吐略降。但业务体验大幅提升。
二十、这次排查真正学到什么
以前我以为:
DPDK 优化就是:提高 PPS。
后来才意识到:
高性能系统真正复杂的是:latency-throughput balance
平衡。
二十一、为什么很多 benchmark 没意义
很多 benchmark 只测:
maximum PPS
但真实业务更关心:
tail latency
例如:
- P99
- P999
因为用户感知的是:最慢请求。不是平均值。
二十二、burst 的本质
burst 本质上是:用 latency 换 throughput。
这是所有高性能网络系统都会做的事情。
包括:
- DPDK
- VPP
- XDP
- SmartNIC
- GPU networking
二十三、工程经验总结
实际项目中:
延迟敏感业务
推荐:
burst 8~16
吞吐优先业务
推荐:
burst 32~64
超高 PPS
可进一步增大。
但必须监控:tail latency。
二十四、总结
为什么 DPDK 程序吞吐很高,但时延越来越大?
很多时候不是:
- CPU 不够
- 网卡问题
- ring bug
而是:burst 过大导致 pipeline 排队。
通过这次问题,我们真正理解了:
核心概念
- batch processing
- burst
- pipeline
- backpressure
- tail latency
- throughput vs latency tradeoff
这也是高性能网络开发真正困难的地方:
系统优化从来不是:“越快越好”。
而是:在吞吐、时延、资源之间找到平衡。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)