我刚开始做DPDK开发时,第一次看到程序运行状态,都会被一个现象吓到:

CPU 100%

而且:不是一个核。

而是:所有 lcore 全部 100%

更奇怪的是:即使没有任何流量。CPU 依然满载。

第一次遇到这个问题时,我甚至怀疑:

  • 程序死循环?
  • 某处卡死?
  • 网卡异常中断?
  • rte_ring 有 bug?
  • worker 空转?

但后来我才意识到:这不是 bug。

而是 DPDK 最核心的设计哲学之一:busy polling

也叫:polling mode

而真正理解它之后,我才明白为什么 DPDK 能做到千万 PPS。

一、问题现场

当时写了一个简单收包程序:

核心代码:

while (1) {
    nb_rx = rte_eth_rx_burst(port, qid, pkts, 32);

    for (i = 0; i < nb_rx; i++) {
        process(pkts[i]);
    }
}

程序启动后:

即使没有任何流量:

top -H

依然显示:

100% CPU

二、第一反应:是不是死循环

因为:代码看起来确实像:

while(1)

无限循环。

于是很多新手第一反应:加 sleep。

例如:

usleep(1);

CPU 瞬间下降。

但:吞吐也直接崩了。

三、为什么加 sleep 会严重掉性能

因为:DPDK 最核心的思想是:主动轮询网卡。

而不是:等待网卡通知。

四、传统 Linux 网络模型

普通 Linux 网络栈:

数据到达时:

NIC
 ↓
interrupt
 ↓
kernel wakeup
 ↓
softirq
 ↓
socket

即:中断驱动。CPU 平时可以休息。

五、DPDK 完全不同

DPDK 使用:DPDK Poll Mode Driver

即:PMD(Poll Mode Driver)

工作方式:

while(1)
    check_rx_queue();

不断轮询。

六、为什么轮询反而更快

很多人第一次听到会很奇怪:

不停空转:怎么会更高效?

其实关键在于:避免中断开销。

七、中断其实很“贵”

一次网络中断:

涉及:

  • interrupt entry
  • context switch
  • scheduler
  • cache pollution
  • softirq

代价很高。

八、尤其在高 PPS 场景

假设:10 Mpps

即:每秒:1000 万包

如果每个包都触发中断:

系统直接崩溃。

九、Linux 为什么会出现 softirq 风暴

因为:

高流量下:CPU 会持续处理中断。

导致:ksoftirqd CPU 100%

这也是传统协议栈的瓶颈之一。

十、DPDK 的核心思想

既然高流量下:CPU 本来就没法休息。

那不如:不要中断。

直接让CPU 永远盯着 RX queue

这样:包一到立刻处理。

十一、这就叫 busy polling

即:CPU 持续轮询硬件。

十二、为什么它性能极高

因为:避免了:

1. 中断切换

2. scheduler 调度

3. 内核唤醒

4. cache miss

CPU cache 始终保持热状态。

十三、cache locality 才是真正关键

DPDK 的高性能核心之一:不是“用户态”。

而是:cache-friendly pipeline。

例如:连续轮询:

RX descriptor
mbuf
ring
flow table

cache 命中率极高。

十四、为什么 idle 时 CPU 仍然 100%

因为:CPU 正在:不停读取 RX queue

即使:没有包。循环仍然存在。

十五、一个典型误区

很多人看到:

CPU 100%

就认为:系统已经满载。

其实:DPDK 中:

CPU busy != CPU overloaded

可能只是:polling。

十六、真正需要关注什么

不是:

CPU usage

而是:

cycles per packet

cache miss

queue depth

latency

十七、为什么 DPDK 程序通常独占 CPU

因为:busy polling 必须:长时间占用核心。

所以:生产环境通常:

isolcpus
taskset
NUMA binding

全部安排上。

十八、进一步理解 PMD

PMD 全称:Poll Mode Driver

即:轮询模式驱动。

本质:CPU 主动“问”网卡:

“有没有包?”
“有没有包?”
“有没有包?”

而不是:网卡中断通知。

十九、为什么小流量场景下 DPDK 反而不划算

因为:

即使:

0 packet

CPU 也在满速轮询。

功耗极高。

二十、这也是为什么 DPDK 更适合

高频交易

UPF

vSwitch

DPI

运营商城关

这些:高 PPS 场景。

二十一、有没有办法降低 idle CPU

有。

DPDK 提供:

power management

以及:

rte_pause();

等机制。

二十二、rte_pause 的作用

例如:

while (1) {
    nb_rx = rte_eth_rx_burst(...);

    if (nb_rx == 0) {
        rte_pause();
        continue;
    }
}

可以降低:pipeline 压力。

二十三、为什么不能直接 sleep

因为:sleep 会导致:

scheduler 介入

cache 冷却

wakeup latency

恢复成本巨大。

二十四、另一个重要知识:polling latency 更稳定

中断模式:

会有:

interrupt coalescing

即:攒包中断。

导致:latency jitter。

而 busy polling:

通常:

tail latency 更稳定

这也是很多低时延系统选择 DPDK 的核心原因。

二十五、一次真实测试

当时做过实验:

interrupt mode

平均 RTT:

80us

但:P99:

2ms

busy polling

平均 RTT:

40us

P99:

60us

稳定很多。

二十六、进一步理解“CPU 100%”

其实:DPDK 中:CPU 100% 更像:核心被专用化。

即:这个核心已经成为:网络数据平面处理器。不再是通用 CPU。

二十七、为什么很多人第一次接触 DPDK 会不适应

因为传统开发习惯:

省 CPU

event-driven

epoll

interrupt

而 DPDK:完全相反:

dedicate core

busy polling

lockless

cache-first

这是两种完全不同的设计哲学。

二十八、这次排查真正学到什么

以前我以为:高性能网络就是:更快的 socket。

后来才意识到:DPDK 本质上是在:用 CPU 换 latency 和 throughput。

它牺牲:

  • CPU 空闲率
  • 功耗
  • 通用性

换取:

  • 极低时延
  • 极高吞吐
  • 更稳定 tail latency

二十九、总结

为什么 DPDK 程序没有流量时 CPU 仍然 100%?

因为:DPDK 使用 busy polling。

CPU 始终在主动轮询网卡。

通过这个问题,我们真正理解了:

核心概念

  • PMD
  • busy polling
  • interrupt vs polling
  • cache locality
  • softirq
  • tail latency

很多时候,DPDK 真正颠覆的不是 API。

而是:整个网络系统的设计思想。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐