DPDK高性能交换机深度实践:一次Hardware Prefetch失效引发的流水线性能崩塌

一、现网故障背景

某运营商数据中心部署了一套基于DPDK的软件交换机。

承担业务:

  • EVPN VXLAN Gateway
  • IPv4/IPv6 Routing
  • ACL Filtering
  • Telemetry
  • Service Chaining

硬件:

项目配置
CPUIntel Xeon Platinum 8480+
NICIntel E810 100G
DPDK23.11
PMD Core48

上线验收:

95Mpps

稳定运行。


运行半年后:

业务规模增长。

Flow数量:

200万
↓
1800万

开始出现:

95Mpps
↓
87Mpps
↓
81Mpps
↓
74Mpps

同时:

RTT P99

0.8ms
↓
3.5ms
↓
6.4ms

二、第一轮排查

检查CPU:

top

结果:

PMD Core
100%

全部跑满。


检查网卡:

rte_eth_stats_get()

结果:

imissed = 0
ierrors = 0
rx_nombuf = 0

正常。


RSS:

48 Queue
均衡

正常。


ACL:

Lookup稳定

正常。


FIB:

DIR24_8
正常

正常。


NUMA:

本地内存命中率正常

正常。


所有传统分析方向全部失败。


三、一个奇怪现象

使用:

perf stat

分析。

发现:

Instructions
基本不变

但:

Cycles
持续增长

表现为:

时间Cycles/Packet
初始132
一个月147
三个月168
六个月213

说明:

CPU执行的代码没变。

但等待时间增加了。


四、DPDK中的Prefetch机制

DPDK经典代码:

for (i = 0; i < nb_rx; i++) {

    rte_prefetch0(
        rte_pktmbuf_mtod(
            pkts[i + 4],
            void *
        )
    );

    process_packet(pkts[i]);
}

核心思想:

提前加载未来数据

如下图:

https://images.openai.com/static-rsc-4/ITxWlsjR4XW_-1TjjK5Nd9aBMW5LoK9Qm3JgLCHtrx60Sl7PSicU3-gFZb8WqO797gxu342YBrEZrnCSMoYMdnajh5g70-sWFHQ0dSZiYVTzvgaARvdwx-IFEek_3mwPv4bo4TnDKBCORoRSpa44eOqSzkLxwo1ryHqGUlV4VbzqOVyJ9lE-Qxy8zNzvwGg9?purpose=fullsize

https://images.openai.com/static-rsc-4/0PIPevB4flUwBXl_2VTqrcBBQ-Vz6coXVqnCyGRbGXm81cyCJPA0Q1UkVMcFgR9ezMUJA3aYrTWRSrgfXmOb2hWCT0IH5seCVpvFS5qciQMeqQRykzlwomnoMD62V9eTQw8PIJ4sPwUbsH0DtOwnigv3lKSzIxAs9zNN6gojHeXJuoZr11CbA6RZak8UTEoN?purpose=fullsize

https://images.openai.com/static-rsc-4/HZUdKaur-gfOvLQ25pgL3BsqW3kY8gAzVQ1PZVcSruUG3S28wquSggP4LYjRz-ZikHY5TjU4hztgf1p2xVRi12u6_gsgrUeYzSog_FYKsVIgN_BV7f0iLRYZpkPIMcWeL7uJMDPPggnirbKf5gTW9ZvBA4Ti8jUz-jTAc4N84xxpzyeSFw29AcEzBWtFnziS?purpose=fullsize


五、很多人忽略的一件事

实际上:

DPDK有两套预取系统。


第一套:

Software Prefetch

即:

rte_prefetch0()

第二套:

Hardware Prefetcher

由CPU自动完成。


Intel CPU中:

包含:

L1 Stream Prefetcher
L2 Stream Prefetcher
Adjacent Line Prefetcher
Spatial Prefetcher

六、为什么开始失效

初始部署时:

流量模式:

大流
长连接

为主。


访问模式:

mbuf
↓
mbuf
↓
mbuf
↓
mbuf

连续。


CPU可以预测:

下一块数据在哪里

于是:

Hardware Prefetch成功率极高。


七、业务变化

半年后:

新增:

微服务
API Gateway
Telemetry

流量变成:

海量短流

访问模式变成:

mbuf1
↓
flowA

mbuf2
↓
flowX

mbuf3
↓
flowB

mbuf4
↓
flowY

访问地址:

完全随机。


八、Prefetch开始失效

CPU预取器本质上是:

预测系统

擅长:

连续访问

例如:

0x1000
0x1040
0x1080
0x10C0

但不擅长:

0x1000
0x8F34000
0x34000
0xFFF000

于是:

Hardware Prefetch命中率下降。


九、第二层放大效应

交换机中:

典型路径:

Packet
 ↓
ACL
 ↓
FIB
 ↓
Neighbor
 ↓
Statistics

每一步:

都会访问:

不同内存区域

当Flow数量达到:

1800万+

时。

这些对象:

远大于LLC

CPU开始频繁等待:

DRAM

返回。


十、Perf证据

分析:

perf top

发现:

热点函数:

fib_lookup()

没变。


但:

backend stalls

显著增加。


统计:

Frontend Bound
8%

Backend Bound
47%

六个月后:

Frontend Bound
9%

Backend Bound
71%

十一、为什么CPU仍然100%

因为:

PMD:

while (1)
{
    rte_eth_rx_burst();
    process();
    rte_eth_tx_burst();
}

永不休眠。


CPU利用率:

100%

不变。


但:

大量时间:

等待内存

而非:

执行指令

十二、关键突破

进一步分析:

perf mem

发现:

大量访问:

flow entry
neighbor entry
stats entry

均呈:

随机访问

模式。


CPU预取器完全失效。


如下图:

https://images.openai.com/static-rsc-4/ii48X0IX5K9-nN9dXt_ujkMzKrzaG-P7lr-bxkUifyAvHMy9i2JCSDod02LyNDoVPZHC9lrOFQWvJaZx9fo1lpsNJQ1IWj8w11oE7N2Zc9GlUfJjjP468C-x3g3N4gnfiFJb1EqJv4wT9bJ7NjeD0Beb-Z3IrnaFPLzLRB1Kf7mgCCnwTBJzC0el5SyDJtTe?purpose=fullsize

https://images.openai.com/static-rsc-4/s_iiqVc1qCd5NlkFtnfTt30o99xWGQZMJUrrbA9f7CdP04hXVsLUIY212QGFQ9QfpilIBziCFRKnubypOflg2zQOsFfxt_OUM56Xt5Tys2ats56R-GaVWmSTW-e2wIMmFeTKd37MBLldizXs4rP1sVzFq80O3b_KmnY804B6wrdR9LI34zIlhDM1yTjqC48h?purpose=fullsize

https://images.openai.com/static-rsc-4/2LMMYhp6hmwUSrx7kcdqY-oYOxdv6Apxfw4-Ma0kk5rVIK7NA0AcV4VVaI_whLix-52FsRvJizZmnJPGQzDlAuHx0u9WKX8t1qmtejIL_aMhKpBnHJ_v-1TLmn6vt8Gl9BwVGrbnEmftKWxzdP4Sm_EbtuNmKV-zquUQ0iTbTYsUSot_di8OK_p5IB5RvEBO?purpose=fullsize


十三、真正根因

完整链路:

Flow增长
      ↓
访问随机化
      ↓
Hardware Prefetch失效
      ↓
DRAM访问增加
      ↓
Backend Stall增加
      ↓
Cycles/Packet增加
      ↓
PPS下降

十四、为什么传统监控发现不了

因为:

不会出现:

丢包

不会出现:

RSS失衡

不会出现:

NUMA错误

不会出现:

Queue拥塞

系统看起来:

完全健康

实际上:

CPU流水线已经大量停顿。


十五、优化方案

方案一:Flow对象重排

原来:

Flow
Neighbor
Stats

分散存储。


改:

Flow + Neighbor

紧邻存储。


减少随机访问。


方案二:冷热分离

热点字段:

struct fast_path_flow

冷数据:

struct flow_metadata

拆分存储。


方案三:扩大Prefetch距离

原来:

prefetch(i+4)

改:

prefetch(i+8)

提高隐藏延迟能力。


方案四:批量查找

原来:

lookup(packet)

改:

lookup(32 packets)

提高访问局部性。


十六、优化效果

优化前:

指标数值
PPS74M
Backend Bound71%
Cycles/Packet213
RTT P996.4ms

优化后:

指标数值
PPS96M
Backend Bound31%
Cycles/Packet136
RTT P990.9ms

如下图展示CPU缓存层次与访问延迟差异:

https://images.openai.com/static-rsc-4/s_iiqVc1qCd5NlkFtnfTt30o99xWGQZMJUrrbA9f7CdP04hXVsLUIY212QGFQ9QfpilIBziCFRKnubypOflg2zQOsFfxt_OUM56Xt5Tys2ats56R-GaVWmSTW-e2wIMmFeTKd37MBLldizXs4rP1sVzFq80O3b_KmnY804B6wrdR9LI34zIlhDM1yTjqC48h?purpose=fullsize

https://images.openai.com/static-rsc-4/XSvd75JfQgcE8BjBKKrs3zfO3C8HDy4jbzbSdfUVqx75VPztr_LefveNTQg9ndTo0P2EDfrpG8KJ17MUP5mKAcqaZw1V2D-DoftjMgsYnLoGNqRJsh3Oy1YCMwQAKzoFQFirnYY6h_yyA_crCYL83BhPywMm7ybZog5HfFqbsKV7JscFkT3310KFsOSi4pkT?purpose=fullsize

https://images.openai.com/static-rsc-4/dtcQMdWDFNPOe35mcUTLUuF3iw_IVaGTDIj1VxxzcoACQ3zspMOoRivQgtcv_OLNKwgwlKgRAia0T_JNhnerNId1HxKIdWoiDmLO25KIV0VdSYj-vCQ2UFkmduSHNjNcpY5GS5hTTt9hbC-J7voZOOmmAbUXdxLfBtm1auy4x8XID3sNdjS8LQ0_8mah1A2C?purpose=fullsize


核心知识点总结

1

DPDK性能问题不一定来自算法。

也可能来自:

访问模式

2

CPU 100%不代表CPU在干活。

可能在:

等待内存

3

DPDK存在两套预取系统:

Software Prefetch
Hardware Prefetch

4

Flow规模增长会改变内存访问模式。


5

随机访问会让Hardware Prefetch失效。


6

现代100G交换机很多瓶颈来自:

Memory Wall

而不是:

Compute Wall

7

真正应该关注的是:

Cycles Per Packet
Backend Stall
Memory Latency

而不仅仅是:

CPU利用率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.HeBoYan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值