虚假的零 CPU 占用:聊聊 vDPA 热迁移与影子队列(SVQ)的工程代价

📅 2026/7/10 21:42:57
虚假的零 CPU 占用:聊聊 vDPA 热迁移与影子队列(SVQ)的工程代价
一个最小的以太网帧,64 字节。它从虚拟机里的virtio-net驱动出发,要到达物理网线。在最朴素的 KVM 配置下,这段路是这样的:guest 驱动把描述符填进 virtqueue,写一下 doorbell,触发一次 VM-exit,控制权掉进 KVM,再被转交给宿主机上的 QEMU 用户态线程,QEMU 把包从 guest 内存里捞出来、拷一份、写进 tap 设备,再经宿主机协议栈上网卡。单核吞吐大概几百 Kpps。换成 vDPA,同样这个包:网卡固件直接 DMA 读走 guest virtqueue 里的描述符,包根本不经过宿主机 CPU,线速 100G,host 侧数据面 CPU 占用约等于零。这两条路的两端,性能差了两个数量级。但如果你把这理解成"vDPA 比 virtio 快 100 倍,所以选 vDPA",你就把一道系统设计题做成了一道跑分题——而且大概率会在上线三个月后,第一次做热迁移的时候,被现实教育。virtio / vhost / vhost-user / vDPA 不是四种互相竞争的"实现",它们是同一份契约(virtqueue 的 ring ABI)在数据面归属上的四个不同落点——数据面从 QEMU 用户态,下沉到宿主机内核,再横移到旁路用户态进程,最终钻进网卡固件。每往硬件方向挪一层,你都在用"可编程性"和"可迁移性"去换"每个包的 CPU 成本"。而 vDPA 把这笔交换推到了极端:它确实把 host CPU 的每包成本降到了零,但代价是把数据面变成了一份你无法打补丁的固件契约;更要命的是,一旦你需要热迁移——虚拟化存在的理由本身——你就得靠 shadow virtqueue 把整条数据面成本原路搬回宿主机 CPU。/