鲲鹏 920 上 DPDK 转发跑不满线速:不是网卡不行,是 CacheLine 从 64 字节变成了 128 字节

举报
yd_236136960 发表于 2026/11/12 17:42:04 2026/11/12
【摘要】 把一个基于 DPDK 的用户态转发程序从 x86 迁到华为云鲲鹏 920 环境,预期是用户态轮询能绕开内核协议栈、吞吐应该很漂亮。实际压测结果很尴尬:小包转发率只有线速的六成左右,perf stat 显示 LLC-load-misses 和 cache-misses 异常高,但 CPU 利用率并没有打满。排查后发现,问题不在 DPDK 本身,而在鲲鹏 920 的 L3 CacheLine 是...

把一个基于 DPDK 的用户态转发程序从 x86 迁到华为云鲲鹏 920 环境,预期是用户态轮询能绕开内核协议栈、吞吐应该很漂亮。实际压测结果很尴尬:小包转发率只有线速的六成左右,perf stat 显示 LLC-load-misses 和 cache-misses 异常高,但 CPU 利用率并没有打满。排查后发现,问题不在 DPDK 本身,而在鲲鹏 920 的 L3 CacheLine 是 128 字节,而 x86 通常是 64 字节——x86 上“刚好不伪共享”的数据布局,在鲲鹏上变成了典型的伪共享。

一、 伪共享在转发路径上从哪来

DPDK 转发程序的核心数据结构是每核独立的统计计数器和 ring 的消费者/生产者索引。x86 上常见的写法是把一组计数器放在结构体里,相邻计数器之间不加填充,因为 64 字节的 CacheLine 通常能“装下”一组逻辑上相关的计数,只要不同核不写同一行就不会争用。但在鲲鹏 920 上,L3 CacheLine 是 128 字节,原来在 64 字节边界上互不相干的两个变量,可能落在了同一个 128 字节行里。一个核更新自己的计数器,就会把另一个核正在读的 CacheLine 标记为 Invalid,导致后者反复从远端 NUMA 节点重新加载——转发路径上的每次 ring 操作都被放大成了缓存一致性流量。

二、 解决方案:填充对齐 + 显式隔离

官方推荐的解决方式是 Padding、变量对齐和线程局部化。具体到 DPDK 转发程序,两个地方必须处理:

1. 每核统计结构体按 128 字节对齐并填充。 不要依赖编译器默认的 alignas(64),在鲲鹏上要显式按 128 字节对齐,并在每个核的结构体尾部填充到 128 的整数倍,确保不同核的计数器绝不共享同一个 L3 CacheLine。

c
struct __attribute__((aligned(128))) per_core_stats {
    uint64_t rx_pkts;
    uint64_t tx_pkts;
    uint64_t rx_bytes;
    uint64_t tx_bytes;
    char pad[128 - (4 * sizeof(uint64_t))];
};
2. ring 的生产者/消费者索引也要隔离。 DPDK 的 rte_ring 本身已经考虑了 CacheLine 对齐,但如果应用层在 ring 之外又包了一层自己的队列元数据,同样需要按 128 字节做隔离。用 perf c2c 或 perf stat -e cache-misses,LLC-load-misses 在优化前后做对比,能直接看到伪共享引发的缓存失效是否下降。

三、 NUMA 约束:绑核不是可选项,是前置条件

伪共享修好之后,还需要确保转发核和网卡在同一个 NUMA 节点上。鲲鹏 920 是多 NUMA 架构,如果网卡中断/队列所在的 NUMA 节点与转发线程绑定的 CPU 不在同一节点,每次 DMA 和内存访问都要跨节点,延迟和带宽都会劣化。DPDK 的 EAL 参数中,-c 指定的 CPU 掩码必须与网卡所在 NUMA 节点的 CPU 集合一致,网卡多队列的绑核也要按网卡的 NUMA 节点来分配。系统启动参数中隔离 CPU(isolcpus、nohz_full)同样要限定在目标 NUMA 节点范围内,避免隔离了错误的核。另外,vm.zone_reclaim=0 和关闭 irqbalance 是 DPDK 场景的常规配置,前者防止从其他 NUMA 节点回收内存引入抖动,后者避免内核把网卡中断在核之间来回迁移。

四、 大页:转发场景的隐性收益

DPDK 的 mbuf 和 ring 都依赖大页内存。鲲鹏环境在支持 1G 大页时优先使用 1G 大页,减少 TLB Miss 对转发路径的干扰。大页不是“配了就行”,要确认预留的页数足够覆盖 mbuf pool 和 ring 的总量,否则 DPDK 初始化阶段就会失败。

五、 总结

鲲鹏 920 上 DPDK 转发的性能瓶颈,往往不在网卡或 DPDK 版本,而在从 x86 带过来的内存布局假设。排查链路:先确认每核统计结构体和 ring 元数据是否按 128 字节 CacheLine 做了隔离 → 再用 perf c2c 验证伪共享是否消除 → 然后确认转发核与网卡同 NUMA 节点并正确绑核 → 最后检查大页配置是否覆盖 mbuf/ring 需求。CacheLine 从 64 到 128 的变化不是“细节”,在转发这种每微秒都在读写共享结构的场景里,它就是线速能不能跑满的分水岭。

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。