はじめに
前回(Day5)では、virtio-net が仮想 NIC の標準でありながら、パケット処理が QEMU に集中し、ユーザー空間とカーネル空間の往復(context switch)が性能上の大きな壁になることを整理しました。
今回は、この課題に対処するために生まれた以下の 2 つの高速化方式を解説します。
- vhost-net:処理をカーネル側へ寄せる方式(kernel offload)
- vhost-user:処理をユーザー空間に寄せる方式(user-space offload)
どちらも virtio の仕組みを基盤にしていますが、高速化のアプローチは大きく異なります。これらを理解することで、「virtio の高速化パス」の体系がはっきり見えてきます。
virtio-net の限界(Day5 の振り返り)
virtio-net では、パケットは次の経路をたどります。
VM(virtio-net)→ QEMU(ユーザー空間)→ ホストカーネル → NICこの構造には次のボトルネックがあります。
- QEMU スレッドに負荷が集中する
- context switch が多く、レイテンシが増える
- PPS(packet per second)が増えると急激に頭打ちになる
これらの課題に対処するために vhost-net と vhost-user が登場します。
vhost-net:virtio をカーネルへ寄せる高速化
vhost-net の構造
vhost-net は、virtqueue の処理を QEMU からカーネルスレッド(vhost thread)へ移す 仕組みです。
VM → virtio-net → vhost thread(カーネル)→ NICQEMU が行っていた virtqueue の読み書きをカーネル側が担当するため、次の効果が得られます。
- QEMU の負荷が大幅に減る
- context switch が減少
- 割り込み処理が効率化
- PPS が安定しやすくなる
実際、10GbE クラスでも vhost-net を有効化するだけで数割の性能改善が見られます。
それでも残る制約
vhost-net は「virtio をカーネルに寄せただけ」であり、データパス自体は従来どおりホストカーネルを通ります。
ホストカーネルには以下の処理レイヤが存在します。
- Linux ネットワークスタック
- softirq
- qdisc
- Linux bridge / OVS(kernel datapath)
つまり、Linux カーネルという構造そのものがボトルネックになるケースでは、vhost-net でも限界があり、この壁を超えるために生まれたのが vhost-user です。
vhost-user:virtio をユーザー空間に寄せる高速化
vhost-user の構造
vhost-user は、virtqueue のメモリ情報を UNIX ドメインソケット経由でユーザー空間アプリケーションへ公開する方式です(ソケットは制御メッセージの交換だけに使われ、実際のパケットバッファは共有メモリ上で読み書きされます)。
典型的な構成:
VM → virtio-net → vhost-user backend(ユーザー空間)→ NIC(DPDK PMD)QEMU は「virtqueue セットアップ」だけを担当し、データパスからは完全に退場します。
kernel bypass(カーネル回避)
vhost-user の最大の利点は、Linux カーネルのネットワークスタックを完全に回避できる点です。
DPDK の Poll Mode Driver(PMD)により、以下を実現します。
- 割り込みを使わない
- context switch がほぼゼロ
- メモリコピーが最小化
- NUMA ローカリティを最大活用
そのため、以下の要件では vhost-user を採用するケースがよくあります。
- NFV(仮想ルーター/FW)
- 25GbE/40GbE/100GbE の高速パケット処理
- 大量 PPS が要求される処理
vhost-user の重要な注意点
vhost-user は DPDK 必須ではない
仕様上、vhost-user backend は「ユーザー空間アプリ」であれば自由に実装できるため、DPDK が絶対条件ではありませんが、以下の理由から、DPDK を使わない vhost-user は 性能的に vhost-net を越えられません。
- Linux カーネルスタックが残る
- PMD thread なし
- hugepage なし
- kernel bypass できない
DPDK が使えない環境ではどうなる?
hugepage・PMD thread が使えない環境では、ユーザー空間高速化(kernel bypass)がそもそも不可能です。この場合、virtio 系の最大性能は vhost-net になります。
vhost-user(DPDKなし)は性能向上の意味が薄く、構成の複雑さだけが増えてしまいます。
つまり、vhost-user が本領を発揮するのは「DPDK + PMD thread」とセットの場合であり、それ以外では vhost-net が適切な選択肢となり、それ以上は SR-IOV となります。
virtio-net / vhost-net / vhost-user の比較
| 項目 | virtio-net(標準) | vhost-net(kernel offload) | vhost-user(user-space offload) |
|---|---|---|---|
| 処理主体 | QEMU(ユーザー空間) | カーネル(vhost thread) | ユーザー空間(DPDK/OVS-DPDK など) |
| QEMU 負荷 | 最大 | 大幅に減少 | ほぼゼロ |
| データパス | QEMU → カーネル | カーネル内 | ユーザー空間内(DPDK PMD 等) |
| kernel bypass | なし | なし | あり(DPDK 使用時) |
| 割り込み | 多い(virtqueue 処理も QEMU) | 減るが存在 | 基本ゼロ(polling) |
| context switch | 多い | 減少 | 最小 |
| 必要要件 | 特になし | 特になし | hugepage / CPU pinning(DPDK 時) |
| ネットワーク制御(帯域制限/ACL) | カーネル/OVS 依存 | カーネル/OVS 依存 | 基本使えない(DPDK 側で実装) |
| 最大 PPS | 低~中 | 中 | 非常に高い(数倍以上) |
| DPDK 必須? | もちろん不要 | 不要 | 仕様上不要だが、性能目的では実質必須 |
| 適用例 | ほとんどの汎用 VM | 高負荷な汎用 VM、一般サーバー | NFV、vRouter、OVS-DPDK、高速パケット処理 |
| DPDK不可環境での最適解 | 標準 | 最適解 | 利点ほぼなし |
- virtio-net → vhost-net は同じアーキテクチャ内での高速化と言えます。互換性を保ったまま性能を底上げする、保守性の高い改善策です。
- vhost-user はアーキテクチャそのものが別物になります。性能は圧倒的ですが、構築と運用が別世界であり、NFV 専用の特殊解とも言えます。
まとめ
vhost-net と vhost-user は、virtio-net の高速化を実現するための重要な技術ですが、適用領域がまったく異なります。
vhost-net
- QEMU の負荷を大幅に削減
- 従来構成をほぼそのまま高速化
- DPDK 不可環境では virtio の最適解
vhost-user
- データパスをユーザー空間へ移し、kernel bypass を実現
- 最大性能を引き出すには DPDK が実質必須
- 高 PPS・高速 NIC(25GbE〜)では必須のアプローチ
次回(Day7)は、virtio を高速化するもう一つのアプローチであるSR-IOV / PCI Passthrough を整理します。


