接上文为什么Burst越大时延反而越高——一次P99.99时延飙升事故彻底理解DPDK Burst处理模型上-CSDN博客九、真正的问题Head-of-Line Blocking队首阻塞很多人第一次看到下面这段代码时都不会觉得有什么问题nb_rx rte_eth_rx_burst(port, queue, pkts, 128); for (i 0; i nb_rx; i) { process_packet(pkts[i]); } rte_eth_tx_burst(...);但是真正的问题就在这里。假设一个Burst收到了128个包平均每个包处理1 us那么第一个包什么时候发送答案第128个包 处理完成以后。于是第一个包虽然最早到达。却必须等待后面127个包全部完成。如果处理128个包需要128 us那么第一个包天然增加约127 us而最后一个包几乎不用等待。这就是Head-of-Line Blocking。Burst越大、第一个包等待越久。十、为什么平均时延几乎没有变化很多工程师第一次看到监控时都会疑惑如果第一个包等待了100多微秒为什么平均时延几乎没变化原因就在于等待并不是平均分配的。例如Burst32每个包处理1 us那么第1个包等待31 us第2个等待30 us……第31个等待1 us第32个等待0 us平均等待只有15.5 us如果Burst128。平均等待约63.5 us因此平均值变化并没有想象中那么夸张。但是第一个包却增加了四倍。于是P99、P99.9、P99.99全部开始增加。十一、为什么VoNR最先出问题很多业务对平均时延并不敏感。例如文件下载、视频播放、数据库批量同步。但是VoNR、VoIP、在线游戏、金融交易。非常关注Tail Latency。例如一个20ms语音帧。如果偶尔某几个UDP包等待5ms。播放器立即开始Jitter Buffer。继续严重一点。开始丢帧。用户听到声音断断续续。而吞吐依旧100%。CPU依旧100%。网络没有丢包。所以传统监控几乎发现不了。十二、Intel为什么一直推荐32很多人认为Intel Sample#define MAX_PKT_BURST 32只是经验值。其实不是。Intel在多代网卡以及DPDK示例程序中长期采用32背后的考虑主要来自三个方面第一Descriptor批处理效率已经足够高。一次读取32个RX Descriptor能够很好地利用Cache局部性PCIe DMA也保持较高效率再继续增大收益开始迅速下降。第二CPU流水线已经被充分填满。现代CPU拥有较深的乱序执行和预取能力32个数据包通常已经足够形成稳定的处理流水线。继续增加Burst并不会让CPU“更忙”反而会延长一个批次完成的时间。第三时延开始成为主导因素。从32增加到64吞吐提升通常只有几个百分点从64增加到128很多场景甚至没有明显提升但Tail Latency却可能成倍增长。因此32并不是一个神奇数字而是在大多数网络设备上兼顾吞吐和时延后的工程折中点。十三、Burst越大Cache一定越好吗很多文章都会说Burst越大。Cache命中率越高。这句话只有一半正确。确实Burst从1 ↓ 8 ↓ 16 ↓ 32CPUPrefetch、L1、L2命中率都会提高。但是。继续32 ↓ 64 ↓ 128Working Set开始扩大。例如每个mbuf假设256Byte。Burst32。就是8KBBurst128。就是32KB已经接近L1 Data Cache。如果Session、ACL、NAT、Metadata全部一起访问。Working Set继续增加。CPU开始频繁访问L2甚至L3。Cache优势开始下降。因此Burst并不是越大越好。十四、现代高性能系统如何解决越来越多的高性能网络设备并不是固定使用一个Burst值而是根据当前流量动态调整。典型思路包括流量很小时立即处理避免为了凑满一个Burst而增加等待时间。流量中等时采用16或32兼顾Cache效率和时延。流量接近线速时适当增大Burst提高吞吐。有些系统甚至会结合RX Ring剩余Descriptor数量当前Worker处理时长最近几个轮询周期的收包数量动态决定下一次调用rte_eth_rx_burst()的目标数量。这种策略通常称为Adaptive Burst自适应Burst。它的目标不是追求最大的Burst而是在不同业务负载下动态寻找吞吐与时延之间的最佳平衡点。十五、结合UPF为什么固定32是一个合理选择回到我们前面讨论过的UPF架构。一个Worker一次处理的数据包包括RX ↓ GTP-U解析 ↓ Session Lookup ↓ PDR ↓ FAR ↓ QER ↓ URR ↓ NAT可选 ↓ IPv4/IPv6重封装 ↓ TX这条路径比L2/L3交换机复杂得多。每个包不仅需要解析多个协议头还需要访问Session、PDR、FAR等状态数据。如果Burst过大一个批次处理时间变长Session等热点数据更容易挤出L1 Cache前面的数据包等待后面的数据包完成Tail Latency快速上升。因此在UPF场景下固定32既能够充分利用Burst带来的批处理优势又不会让单批次处理时间过长是一个经过大量工程实践验证的合理选择。这也是为什么不少成熟的DPDK数据面项目在没有特殊需求时都采用32作为默认值。十六、不同业务推荐的Burst大小实际工程中并不存在适用于所有场景的统一Burst值。可以参考下面的经验场景推荐Burst主要目标高频交易HFT14极低时延VoIP / VoNR816降低Tail Latency5GC UPF1632吞吐与时延平衡L3交换机32综合性能最佳DPI / IPS3264计算密集型离线分析64128最大吞吐这里需要强调的是这些数值只是工程经验而不是固定规则。最终仍应根据CPU架构NIC型号报文大小业务类型时延目标进行实际测试和调优。十七、事故复盘故障最终恢复的方法非常简单#define MAX_PKT_BURST 128恢复为#define MAX_PKT_BURST 32重新上线后指标修改前128恢复后32吞吐93.6 Gbps91.8 GbpsCPU100%100%平均时延19 us18 usP99165 us39 usP99.9740 us65 usP99.997.6 ms122 usVoNR卡顿有消失团队最终接受了一个事实为了约2%的吞吐提升却付出了数十倍Tail Latency增长的代价这并不是一次成功的优化。十八、写在最后DPDK引入Burst模型并不是因为“一次处理更多包一定更快”而是为了降低函数调用、Doorbell访问、Descriptor同步和Cache访问带来的固定开销。但是Burst是一种批处理机制而批处理天然意味着等待。随着Burst不断增大Descriptor访问效率提升会逐渐趋于饱和Cache Working Set不断扩大一个批次完成时间不断延长Head-of-Line Blocking越来越明显Tail Latency快速恶化。因此在现代高性能数据面中优化目标已经不再只是追求最高吞吐而是在吞吐、CPU利用率、Cache效率和尾时延之间寻找平衡点。对于大多数DPDK交换机、UPF和网络安全设备而言32并不是一个神秘数字而是长期工程实践形成的一个合理折中点。真正优秀的数据面架构不会盲目追求更大的Burst而是根据业务特点选择最适合的Burst策略必要时采用自适应Burst让系统在不同负载下都保持稳定的性能表现。
为什么Burst越大,时延反而越高?——一次P99.99时延飙升事故,彻底理解DPDK Burst处理模型(下)
发布时间:2026/7/8 13:01:58
接上文为什么Burst越大时延反而越高——一次P99.99时延飙升事故彻底理解DPDK Burst处理模型上-CSDN博客九、真正的问题Head-of-Line Blocking队首阻塞很多人第一次看到下面这段代码时都不会觉得有什么问题nb_rx rte_eth_rx_burst(port, queue, pkts, 128); for (i 0; i nb_rx; i) { process_packet(pkts[i]); } rte_eth_tx_burst(...);但是真正的问题就在这里。假设一个Burst收到了128个包平均每个包处理1 us那么第一个包什么时候发送答案第128个包 处理完成以后。于是第一个包虽然最早到达。却必须等待后面127个包全部完成。如果处理128个包需要128 us那么第一个包天然增加约127 us而最后一个包几乎不用等待。这就是Head-of-Line Blocking。Burst越大、第一个包等待越久。十、为什么平均时延几乎没有变化很多工程师第一次看到监控时都会疑惑如果第一个包等待了100多微秒为什么平均时延几乎没变化原因就在于等待并不是平均分配的。例如Burst32每个包处理1 us那么第1个包等待31 us第2个等待30 us……第31个等待1 us第32个等待0 us平均等待只有15.5 us如果Burst128。平均等待约63.5 us因此平均值变化并没有想象中那么夸张。但是第一个包却增加了四倍。于是P99、P99.9、P99.99全部开始增加。十一、为什么VoNR最先出问题很多业务对平均时延并不敏感。例如文件下载、视频播放、数据库批量同步。但是VoNR、VoIP、在线游戏、金融交易。非常关注Tail Latency。例如一个20ms语音帧。如果偶尔某几个UDP包等待5ms。播放器立即开始Jitter Buffer。继续严重一点。开始丢帧。用户听到声音断断续续。而吞吐依旧100%。CPU依旧100%。网络没有丢包。所以传统监控几乎发现不了。十二、Intel为什么一直推荐32很多人认为Intel Sample#define MAX_PKT_BURST 32只是经验值。其实不是。Intel在多代网卡以及DPDK示例程序中长期采用32背后的考虑主要来自三个方面第一Descriptor批处理效率已经足够高。一次读取32个RX Descriptor能够很好地利用Cache局部性PCIe DMA也保持较高效率再继续增大收益开始迅速下降。第二CPU流水线已经被充分填满。现代CPU拥有较深的乱序执行和预取能力32个数据包通常已经足够形成稳定的处理流水线。继续增加Burst并不会让CPU“更忙”反而会延长一个批次完成的时间。第三时延开始成为主导因素。从32增加到64吞吐提升通常只有几个百分点从64增加到128很多场景甚至没有明显提升但Tail Latency却可能成倍增长。因此32并不是一个神奇数字而是在大多数网络设备上兼顾吞吐和时延后的工程折中点。十三、Burst越大Cache一定越好吗很多文章都会说Burst越大。Cache命中率越高。这句话只有一半正确。确实Burst从1 ↓ 8 ↓ 16 ↓ 32CPUPrefetch、L1、L2命中率都会提高。但是。继续32 ↓ 64 ↓ 128Working Set开始扩大。例如每个mbuf假设256Byte。Burst32。就是8KBBurst128。就是32KB已经接近L1 Data Cache。如果Session、ACL、NAT、Metadata全部一起访问。Working Set继续增加。CPU开始频繁访问L2甚至L3。Cache优势开始下降。因此Burst并不是越大越好。十四、现代高性能系统如何解决越来越多的高性能网络设备并不是固定使用一个Burst值而是根据当前流量动态调整。典型思路包括流量很小时立即处理避免为了凑满一个Burst而增加等待时间。流量中等时采用16或32兼顾Cache效率和时延。流量接近线速时适当增大Burst提高吞吐。有些系统甚至会结合RX Ring剩余Descriptor数量当前Worker处理时长最近几个轮询周期的收包数量动态决定下一次调用rte_eth_rx_burst()的目标数量。这种策略通常称为Adaptive Burst自适应Burst。它的目标不是追求最大的Burst而是在不同业务负载下动态寻找吞吐与时延之间的最佳平衡点。十五、结合UPF为什么固定32是一个合理选择回到我们前面讨论过的UPF架构。一个Worker一次处理的数据包包括RX ↓ GTP-U解析 ↓ Session Lookup ↓ PDR ↓ FAR ↓ QER ↓ URR ↓ NAT可选 ↓ IPv4/IPv6重封装 ↓ TX这条路径比L2/L3交换机复杂得多。每个包不仅需要解析多个协议头还需要访问Session、PDR、FAR等状态数据。如果Burst过大一个批次处理时间变长Session等热点数据更容易挤出L1 Cache前面的数据包等待后面的数据包完成Tail Latency快速上升。因此在UPF场景下固定32既能够充分利用Burst带来的批处理优势又不会让单批次处理时间过长是一个经过大量工程实践验证的合理选择。这也是为什么不少成熟的DPDK数据面项目在没有特殊需求时都采用32作为默认值。十六、不同业务推荐的Burst大小实际工程中并不存在适用于所有场景的统一Burst值。可以参考下面的经验场景推荐Burst主要目标高频交易HFT14极低时延VoIP / VoNR816降低Tail Latency5GC UPF1632吞吐与时延平衡L3交换机32综合性能最佳DPI / IPS3264计算密集型离线分析64128最大吞吐这里需要强调的是这些数值只是工程经验而不是固定规则。最终仍应根据CPU架构NIC型号报文大小业务类型时延目标进行实际测试和调优。十七、事故复盘故障最终恢复的方法非常简单#define MAX_PKT_BURST 128恢复为#define MAX_PKT_BURST 32重新上线后指标修改前128恢复后32吞吐93.6 Gbps91.8 GbpsCPU100%100%平均时延19 us18 usP99165 us39 usP99.9740 us65 usP99.997.6 ms122 usVoNR卡顿有消失团队最终接受了一个事实为了约2%的吞吐提升却付出了数十倍Tail Latency增长的代价这并不是一次成功的优化。十八、写在最后DPDK引入Burst模型并不是因为“一次处理更多包一定更快”而是为了降低函数调用、Doorbell访问、Descriptor同步和Cache访问带来的固定开销。但是Burst是一种批处理机制而批处理天然意味着等待。随着Burst不断增大Descriptor访问效率提升会逐渐趋于饱和Cache Working Set不断扩大一个批次完成时间不断延长Head-of-Line Blocking越来越明显Tail Latency快速恶化。因此在现代高性能数据面中优化目标已经不再只是追求最高吞吐而是在吞吐、CPU利用率、Cache效率和尾时延之间寻找平衡点。对于大多数DPDK交换机、UPF和网络安全设备而言32并不是一个神秘数字而是长期工程实践形成的一个合理折中点。真正优秀的数据面架构不会盲目追求更大的Burst而是根据业务特点选择最适合的Burst策略必要时采用自适应Burst让系统在不同负载下都保持稳定的性能表现。