为什么 DPDK VirtIO 只能跑到 40Gbps?—— 一次 KVM 虚拟交换机性能瓶颈定位全过程(上)

发布时间:2026/7/17 9:26:05
为什么 DPDK VirtIO 只能跑到 40Gbps?—— 一次 KVM 虚拟交换机性能瓶颈定位全过程(上) 一、一个令人困惑的现网问题某云计算厂商上线了一套基于DPDK KVM的高性能虚拟交换平台。整体网络架构如下┌──────────────┐ │ Physical NIC │ │ Intel E810 │ └──────┬───────┘ │ DPDK vSwitch │ vhost-user │ QEMU/KVM │ VirtIO-Net │ Guest DPDK设计目标非常明确物理网络100GbEGuestDPDK PMD宿主机DPDK vSwitchZero Copy单 VM 满速接近 100Gbps实验室测试中小包、大包都表现正常。然而真正上线以后监控平台却发现了一个奇怪的现象包长理论吞吐实际吞吐64 Bytes100Gbps36~40Gbps512 Bytes100Gbps42Gbps 左右1500 Bytes接近 100Gbps92~95Gbps也就是说只有小包性能异常。更奇怪的是宿主机 CPU平均利用率 48%Guest CPU42%PMD没有忙轮询瓶颈。Descriptor没有耗尽。没有任何RX Miss TX Error No Mbuf Ring Full整个系统看起来一切正常。但是吞吐率就是上不去。二、所有人都认为是 PMD 性能不足第一次排查时。整个团队几乎一致认为一定是 PMD 跑满了。于是开始查看dpdk-proc-info --stats所有 Port统计如下RX packets : 正常 TX packets : 正常 RX errors : 0 TX errors : 0 RX no mbuf : 0 RX missed : 0继续查看PMD LoopCPU 42% Idle 58%这意味着PMD并没有跑满。于是有人开始怀疑RSS是不是分布不均检查RSS所有 QueueQueue0 Queue1 Queue2 Queue3 ...... Packets 基本一致RSS正常。继续NUMA。结果Guest Memory Local Host HugePage Local NIC LocalNUMA也没有问题。到这里整个团队几乎陷入了僵局。三、问题真的发生在 VirtIO 吗为了进一步定位。我们绕开 Guest。直接HostDPDK转发E810结果98Gbps完全正常。说明DPDK没有问题。继续绕开VirtIO。改成SR-IOV VF直通Guest再次测试96Gbps依然正常。问题第一次真正开始收敛。如果Host正常、Guest、DPDK正常、SR-IOV正常。那么唯一发生变化的。只有VirtIO vhost-user整个团队开始把目光放到VirtIO。四、Perf 火焰图暴露了真正的热点为了定位到底CPU时间花在哪里。我们在Host运行perf record -g随后生成火焰图。得到如下热点vhost_worker() │ vring_avail_event() │ vring_need_event() │ eventfd_write() │ syscall占比超过31%继续Guest采样结果热点几乎全部集中virtio_recv_pkts() ↓ virtqueue_get_buf() ↓ used_idx这里第一次出现一个陌生名字Virtqueue。也是VirtIO性能真正开始分化的地方。五、VirtIO 真正的数据通路很多人认为VirtIO就是共享内存。实际上真正的数据流远比想象复杂。整体过程如下Guest mbuf │ ▼ VirtIO Driver │ ▼ Descriptor Table │ ▼ Available Ring │ ▼ Kick Host │ ▼ vhost-user │ ▼ Host DPDK │ ▼ NIC DMA如果反方向则Host完成DMA以后。继续Used Ring ↓ Notify Guest ↓ Guest PMD ↓ mbuf看到这里。很多开发者都会觉得没有什么特别。其实真正的问题。并不是Descriptor。而是后面的两个动作。Kick Notify六、真正拖慢性能的不是拷贝而是通知Notification很多开发者第一次接触 VirtIO 时都会重点关注Descriptor 是否连续是否 Zero Copy是否发生数据拷贝这些当然重要。但在高 PPSPackets Per Second场景下真正限制性能的往往不是数据路径而是控制路径。对于每一批发送完成的数据Guest 都需要通知 Host“新的 Descriptor 已经准备好了。”这个动作称为Kick同样Host处理完成以后。又需要通知GuestNotify如果每一个Burst都Kick。Host就需要不停响应通知。CPU不断发生Guest ↓ VM Exit ↓ KVM ↓ vhost-user ↓ 继续处理而VM Exit正是整个虚拟化里面最昂贵的操作之一。为什么小包只能40Gbps真正答案开始慢慢浮现。未完待续