DPDK高性能交换机深度实践:一次Mempool Cache失衡引发的百万级PPS性能雪崩

一、故障背景

某大型云数据中心部署了一批DPDK软件交换机。

主要功能:

  • EVPN VXLAN Gateway
  • IPv4/IPv6 Routing
  • ACL
  • QoS
  • ERSPAN

硬件:

项目配置
CPUXeon 8480+
NICIntel E810
DPDK23.11
PMD48核
Queue48 RX / 48 TX

上线初期:

97Mpps

长期稳定。


半年后:

随着业务增长。

开始出现:

97Mpps
↓
91Mpps
↓
84Mpps
↓
69Mpps

同时:

P99 RTT
0.7ms
↓
4.1ms

但:

CPU始终:

100%

二、第一轮排查

检查:

rte_eth_stats_get()

结果:

imissed=0
rx_nombuf=0
ierrors=0

正常。


RSS:

48队列均衡

正常。


ACL:

Lookup稳定

正常。


FIB:

DIR24_8稳定

正常。


NUMA:

Local Memory
98%以上

正常。


问题无法解释。


三、发现一个奇怪现象

通过:

dpdk-proc-info

统计Mempool。

发现:

mempool剩余对象很多

并不存在:

对象耗尽

问题。


但:

mempool_get_bulk()

耗时却越来越高。


这是第一条关键线索。


四、DPDK Mempool架构

很多人认为:

Mempool
=
共享对象池

其实不准确。

真正架构如下:

https://images.openai.com/static-rsc-4/2nJyF16j6Htk2MLEgFCqEm0tlqjY6x_KKyCBz8lPcbnPs8Ek91E0O8p_Vkf2Yee9n-L7o8eKMaCL34PFsctLg1OIIovo9E8HML_sCglI-gSvOwDeojA5fEeYhDOa2wkNyVMm7KBxeqkunbioKuA30Ve7uNwhc9sjwVleElQv7vNat8EsRdIwC6GZvse7vRif?purpose=fullsize

https://images.openai.com/static-rsc-4/dR45ze553L1gWNpIhsXqGQUysTF_g7dw6HnCIEKi-XEw39taj7073nAL_E9WKQXipqclr2Acok0v22ya01S-3nYtw97qUhyJXwWiOXcNrRKsFb3WHDD-wRxW4MZsaQzdbFZMMPrJJJi_Ff6yFXk-OeConsD6XW02ylCejKqtpqGkCEvvmG42Mgw7WhRXDLk1?purpose=fullsize

https://images.openai.com/static-rsc-4/OqrDgZy0B_WH7VfuhQReScITlshiddzZQvlfYFIaYrMRh-vgZ-Cij4_S_qL_jGOg_G2JhmKqK01-b7rFBUPfW9pus2B7xfAmKqdBflI6nKvo8BiwolsXigqlY4AlR-k06hRhfaeDQawPdjM8Aeo7nB-4_WTBbc4slw-62r1QSW2HOHQtQkvtfbG7ujvptLqc?purpose=fullsize

结构:

Global Pool
     ↑↓
Per-Lcore Cache
     ↑↓
PMD Thread

核心思想:

尽量避免访问Global Pool。


五、Per-Core Cache工作机制

假设:

cache_size = 256

Core0申请mbuf:

rte_pktmbuf_alloc()

优先:

Core0 Cache

获取。


只有Cache空了:

才访问:

Global Pool

释放时:

也是一样。


六、为什么这么设计

因为:

Global Pool内部:

共享

意味着:

CAS
Lockless同步
Cache一致性

成本。


而:

Per-Core Cache:

本地访问

几乎零成本。


七、问题开始出现

交换机新增:

ERSPAN
Mirror
Sampling

功能。


出现:

Core0分配
Core17释放

情况。


即:

Allocate Core ≠ Free Core

八、生命周期被破坏

正常情况:

Core0
Alloc
 ↓
Process
 ↓
Free

异常:

Core0
Alloc

↓

Core17
Free

如下图:

https://images.openai.com/static-rsc-4/Xk-r4a-euUFwCDDqZ9JFjhf2sUI_Ep3Y3ignUIs6UzxFQHxPRogJx_SdbYvVJu3sWGspIV_1oZ9GfBh94GH1ahcMYM9nCv2ozYqIHSX9PIG_T_zvGgIdIxuFFuPDD6QGt2TpYIIwYgCVDjSuPvyTEeoOp19SkW4tiuauhmfDoRcCDJPIzXB2L7pPx-TtcfLP?purpose=fullsize

https://images.openai.com/static-rsc-4/Z7KBFPXtvSTSbiRcwxyQA3qX5TczHWPJeN4iapcizJNE_p19qQqIfxv4uq1EOZ3o2iQhASlE9qWMZLnh5DFgy1aT01SrK5h0vTfy8RoQ81uoewCA6wRFxCrJBO1eFCavzEqy6wOorFx-aBddxk_rKiu_zbGSabF22o7hFqvRYNTsAOvgWsQvjvy2HAG9VPnc?purpose=fullsize

https://images.openai.com/static-rsc-4/4HYXbYtGpg-dBLPSnYqDxmq7j9M1HwMSHlS8k6SSA9Uor84kcR1nKBYXFZoOn0Kn4tl45znl4cL9vSo98dqxB_IzMvdoyO4aGzTgNSaHZQ-75wUFKN0oLwoGGs7tolCsBo_JBdELNpkF7V-JA1yHHWzb9M20YB309dqxubXXNACC65mnvcLgVfP_BUxIskru?purpose=fullsize


结果:

Core17 Cache:

越来越大。

Core0 Cache:

越来越空。


九、Mempool Cache失衡

统计:

CoreCache对象
Core08
Core112
Core25
Core17913
Core181004

出现明显倾斜。


十、第一层性能损失

Core0:

频繁:

rte_mempool_get_bulk()

访问:

Global Pool

次数增加。


导致:

CAS竞争增加

十一、第二层性能损失

Global Pool:

采用:

ring

实现。


大量核心同时访问:

MP/MC

模式。


结果:

atomic竞争

显著增加。


十二、第三层性能损失

更严重的是:

缓存一致性流量。


Global Pool Head:

成为:

热点Cache Line

如下图:

https://images.openai.com/static-rsc-4/A6qO-QgJa1kFe7EXvHuMuFeW_yeQclhvBI99oaGHjCuhNNdxjTOc9vHLKijUql8Ko1VqK1Mv64Us_ZDQPZy8ip1pwMCcxuM3lmXAN0nsZxLntJ-kKm5J2tGe4S-e24r1YQwye5wjVbQSKPNP9YsgfU22u4N-WvEQalQIGeKARY0IagyL93FetwNimBkvvn7o?purpose=fullsize

https://images.openai.com/static-rsc-4/Ucc-oXuLyDtNxM-18gGBEko0LYM3PPmPfbb6x47IKz3Zji0wqcIeop6l_0wpxmlOSSYmNauJOOZX0WcJ9uzjLLPEhFUL_U4vxvcpesin66XogkPpIo2oULQ3smgKDx5dP3CAmqTyibGA3S6mJEXPzwuOIfEHv0mngEDT7y8tRFQ7Ancm44S0-Pu1qEPg-W6-?purpose=fullsize

https://images.openai.com/static-rsc-4/ADZtLwH49rVJxYp47QipUDykFRNYsSsy9nGxkHkrLb1fN-X_5g7l4LGy0gQRpGkyUDw6PDcOKU1YA29WMjt-NY3vgep49O5gNTeyr0fAo3P4ES5UxPVHOcpE2kRQwKH_C2xoRLY89I43cJHBUrBhwyYmfvsKoC1j-o7xRObaCPjJh6rxPXih0UcFZwi8b2ap?purpose=fullsize


缓存线:

Core0
↓
Core7
↓
Core12
↓
Core22

不断迁移。


十三、Perf分析

使用:

perf stat

发现:

Instructions
基本不变

但:

lock instructions

增长:

7倍

同时:

LLC Miss

增长:

4倍

十四、为什么CPU仍然100%

因为:

PMD线程:

while (1)
{
    rx_burst();
    process();
    tx_burst();
}

永不休眠。


CPU:

始终:

100%

但:

越来越多时间:

花费在:

mempool同步

而非:

转发逻辑

十五、关键证据

增加统计:

rte_mempool_ops_get_count()

发现:

Global Pool访问次数:

时间次数/秒
初始12万
异常830万

增长:

69倍

与PPS下降趋势完全一致。


十六、根因闭环

完整链路:

Mirror/Sampling
        ↓
跨核释放
        ↓
Cache失衡
        ↓
Global Pool访问增加
        ↓
Atomic竞争增加
        ↓
Cache Line Bounce
        ↓
Cycles/Packet增加
        ↓
PPS下降

十七、解决方案

方案一

生命周期归属原则。

谁申请:

谁释放

避免:

Cross-Core Free

方案二

引入Recycle Ring。

Core17
 ↓
Recycle Ring
 ↓
Core0回收

恢复对象归属。


方案三

调大Cache Size。

原来:

cache_size=256

改:

cache_size=1024

降低Global Pool访问频率。


方案四

独立Mempool。

不同Pipeline:

RX
Worker
Mirror

使用不同Pool。


降低争用。


十八、优化结果

优化前:

指标数值
PPS69M
RTT P994.1ms
Global Access830万/s
Lock Instr

优化后:

指标数值
PPS96M
RTT P990.8ms
Global Access18万/s
Lock Instr

核心知识点总结

1

Mempool不是简单内存池。

本质是:

Global Pool
+
Per-Core Cache

架构。


2

DPDK性能依赖:

对象局部性

而不仅仅是:

CPU局部性

3

跨核释放会破坏:

Cache Ownership

4

Mbuf生命周期设计错误。

即使:

RSS正常
NUMA正常

也能造成巨大损失。


5

CPU 100%并不代表真正转发。

可能在:

Atomic竞争

上浪费大量周期。


6

高性能交换机设计中:

“谁申请,谁释放”不仅是编码规范,更是性能架构原则。


7

很多百万级PPS性能问题,本质上并不发生在收包、查表、发包阶段,而发生在最容易被忽略的:

Mbuf回收路径

这类问题通常只会在几十核、上亿PPS的真实交换机场景中暴露,也是很多DPDK项目从实验室走向生产环境后才出现的典型深层瓶颈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr.HeBoYan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值