一次100G交换机吞吐周期性下降的故障:DPDK Mempool Cache失衡深度分析(上)
2026/7/10 21:40:54 网站建设 项目流程

一、故障背景

某运营商数据中心部署了一套基于DPDK开发的100G高性能交换机。

系统承担:

  • 二层交换
  • IPv4/IPv6三层转发
  • VXLAN Gateway
  • ACL过滤

服务器配置如下:

配置项参数
CPUIntel Xeon Gold 双路
网卡Intel 100GbE
DPDK24.11 LTS
HugePage1GB HugePage
PMD Worker16个

系统上线半年,一直稳定运行。

某次版本升级以后,压力测试发现一个奇怪现象。

开始10分钟:系统性能正常。

持续运行约30分钟以后:PPS开始出现周期性下降。

每隔几十秒:都会出现一次明显下降。持续时间约几十毫秒。随后恢复正常。

整个过程不断重复。


二、第一轮排查

首先怀疑:

是不是网卡出现异常?

查看DPDK统计:

struct rte_eth_stats stats; rte_eth_stats_get(port, &stats);

结果:

imissed = 0 ierrors = 0 rx_nombuf = 0

继续查看:

ethtool -S eth0

重点统计:

  • CRC Error
  • RX Miss
  • DMA Error
  • Buffer Error

全部为0。

说明:

网卡完全正常。


核心知识点一

DPDK统计的是软件能够观察到的状态。

如果性能下降发生在:

  • Cache竞争
  • 内存分配
  • CPU同步

这些问题通常不会反映到网卡统计信息中。

因此:

没有Error,

并不意味着没有性能问题。


三、第二轮排查

继续观察:

每个PMD Worker。

结果如下:

WorkerCPU
Worker0100%
Worker1100%
Worker2100%
……100%

CPU全部100%。

这完全符合DPDK Poll Mode Driver的工作方式。

继续统计:RSS分布。

发现:16个Worker流量几乎一致。

RX Queue:没有积压。

TX Queue:没有阻塞。

说明:

既不是RSS失衡。

也不是Queue瓶颈。


核心知识点二

DPDK系统中:

CPU利用率并不是判断性能瓶颈的重要指标。

真正需要关注的是:

  • 每Packet Cycle
  • IPC
  • Cache命中率
  • 内存访问模式

四、Perf开始暴露异常

既然:

软件逻辑没有问题。

开始使用:

perf stat \ -e cycles,instructions,cache-misses \ -p <PMD_PID>

得到如下结果:

指标正常阶段抖动阶段
Instructions基本一致基本一致
Cycles略增加↑↑
IPC1.921.61
Cache Miss小幅增加小幅增加

Cache Miss:并没有明显变化。

但是:

CPU执行效率明显下降。

说明:

CPU不是在计算,而是在等待。

等待什么?

继续分析。


五、真正的异常开始出现

为了进一步定位。

我们开启DPDK Telemetry,并增加了Mempool统计:

rte_mempool_avail_count(mp); rte_mempool_in_use_count(mp);

压测过程中发现:

每当系统吞吐下降时:Global Pool对象数量开始剧烈波动。

而Per-lcore Cache几乎全部被耗尽。

几十毫秒后Cache重新填满,性能恢复。

又过一段时间。

再次重复。

这说明:

问题并不是:mbuf数量不足。

而是:mbuf流转路径出现了异常。


核心知识点三

DPDK申请mbuf:

并不是:

每次都访问Global Pool。

真正的数据路径:

首先经过:Per-lcore Cache。

只有Cache不足。

才会访问:Global Pool。

因此:

Per-lcore Cache:才是真正决定高速收发性能的关键。


六、Mempool到底是如何工作的?

很多开发者认为:

Mempool就是一个对象池。

实际上:

DPDK为了减少多核竞争,在Global Pool之外,又增加了一层:Per-lcore Cache。

真正结构如下:

Global Pool │ ┌──────────────┼──────────────┐ │ │ │ Worker0 Cache Worker1 Cache Worker2 Cache │ │ │ mbuf mbuf mbuf

正常情况下:

Worker收包。释放mbuf。再次申请mbuf。几乎全部发生在:自己的Cache里面。

整个过程不会访问Global Pool。

也不会产生跨核竞争。

这也是DPDK能够支撑数亿PPS的重要原因之一。

但是。

如果:Per-lcore Cache配置不合理。

整个机制反而会成为性能瓶颈。


七、问题逐渐浮出水面

继续阅读DPDK源码。

定位到:lib/mempool/rte_mempool.c

其中:rte_mempool_get_bulk()

首先尝试:从Per-lcore Cache获取对象。

只有:Cache不足。

才会访问:Global Ring。

而Global Ring正是:所有Worker共享的资源。

问题:

似乎开始指向这里……

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询