VM パフォーマンス最適化は、CPU、memory、NIC を増やす作業ではありません。どの service indicator が要件を満たしていないかを定義し、guest、QEMU、host、storage、network のどこで仕事が止まっているかを計測し、仮説を 1 つずつ検証する作業です。
この記事では、個別の tuning 手順ではなく、baseline、failure domain、metric、変更、再測定、rollback を一つの workflow にします。CPU pinning、HugePages、IOThread、multiqueue、SR-IOV、DPDK などは、原因と成功条件が明確になった後で選びます。
書籍
CPU 仮想化支援、メモリ仮想化、割り込み、仮想デバイスなど、VM の実行モデルを低レイヤから理解する参考書籍です。価格や在庫はリンク先で確認してください。
Amazon で見るこのリンクは Amazon アソシエイトリンクです。
最適化の前に SLO と workload を定義する
性能要件を CPU 使用率ではなく、利用者または system が必要とする結果で定義します。同じ VM でも、batch completion time を重視する場合と、request の p99 latency を重視する場合では、採用する変更が異なります。
| workload | service indicator | 条件 |
|---|---|---|
| Web / API | request rate、p95 / p99、error rate | 同時接続、payload、cache hit |
| database | transaction rate、query latency、lock wait | dataset、read / write 比率、durability |
| batch | completion time、throughput、retry | input size、worker 数、deadline |
| NFV | pps、throughput、drop、jitter | packet size、flow 数、feature set |
| storage | IOPS、bandwidth、fsync latency | block size、queue depth、read / write 比率 |
- 正常と判定する SLO と許容差
- 通常、peak、障害縮退の workload profile
- 測定時間、warm-up、sample 数
- 同時に動く VM、backup、batch、migration
- 成功条件と rollback 条件
guest から physical resource まで経路を描く
metric を集める前に、VM の処理が通る resource path を確認します。guest で見える device 名と、libvirt target、QEMU thread、host device、backend volume、physical NIC を対応付けます。
| resource | guest | virtualization | host / backend |
|---|---|---|---|
| CPU | process、run queue、steal | vCPU thread、emulator、quota | pCPU、SMT、NUMA、co-tenant |
| memory | working set、fault、swap | balloon、HugePages、numatune | NUMA node、reclaim、KSM |
| storage | filesystem、block queue | virtio、QEMU block、IOThread | filesystem、LVM、Ceph、NVMe |
| network | socket、virtio-net、queue | tap、vhost、bridge、OVS | NIC、IRQ、switch、tunnel |
この対応がないまま host の高負荷 process や device を見ても、対象 VM の workload と関係があるか判断できません。最初に name、ID、interface、disk target、NUMA node を結びます。
baseline は同じ時間窓で採取する
正常時と問題発生時を比較できるよう、guest と host の clock を同期し、同じ開始時刻、間隔、継続時間で metric を採取します。counter は累積値を含むため、区間差分を使います。
date --iso-8601=seconds
uptime
vmstat 1
mpstat -P ALL 1
iostat -xz 1
ip -s link
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/ioLinux の Pressure Stall Information は、CPU、memory、I/O の不足で task が止まった時間を示します。utilization が低くても pressure が増えていれば、別 resource を待って仕事が進んでいない可能性があります。
utilization、pressure、queue、latency を分ける
| metric | 答えること | 単独で判断できない理由 |
|---|---|---|
| utilization | resource が使われた割合 | 高くても SLO を満たす場合がある |
| pressure | resource 不足で task が止まった時間 | どの process が影響を受けたかを追加確認する |
| queue | 処理待ちの仕事量 | 短い spike は平均値に埋もれる |
| latency | 完了までの時間 | throughput と workload 条件が必要 |
| throughput | 単位時間の完了量 | latency と error を犠牲にしていないかを見る |
| error / drop | 完了できなかった仕事 | retry により負荷を増やす場合がある |
平均 CPU、平均 latency、平均 bandwidth だけで合否を決めません。p95 / p99、最大 queue、PSI total の増分、drop、retry を同じ graph または時刻表で比較します。
libvirt で VM と QEMU の統計を取得する
virsh domstats は、domain の CPU、vCPU、memory、block、interface、IOThread、perf などの統計 group を取得できます。hypervisor や domain state によって未提供の field があるため、欠損を 0 とみなしません。
virsh domstats vm01 --state --cpu-total --balloon --vcpu --interface --block --perf --iothread --memory
virsh vcpuinfo vm01 --pretty
virsh vcpupin vm01
virsh emulatorpin vm01
virsh numatune vm01
virsh domblklist vm01 --details
virsh domiflist vm01
virsh dumpxml vm01vcpu.<num>.wait や delay、block の read / write time、interface counter など、利用できる field を区間差分で比較します。XML の設定値と実行時 counter を分け、設定があることだけで効果を断定しません。
failure domain を比較して対象範囲を狭める
| 発生範囲 | 優先して確認する層 |
|---|---|
| 1 process | application、lock、GC、connection pool |
| 1 VM | guest kernel、virtual device、VM XML、QEMU |
| 同じ host の複数 VM | pCPU、NUMA、host I/O、NIC、co-tenant |
| 同じ storage の複数 host | storage network、volume、controller、rebuild |
| 同じ network path | bridge、OVS、firewall、tunnel、uplink |
| 基盤全体 | shared service、capacity、変更、外部 dependency |
正常な VM、別 host、別 storage、別 network path と比較すると、変更せずに仮説を減らせます。個別 VM の tuning は、failure domain を確認した後に行います。
仮説は原因、根拠、反証条件を一組にする
| 仮説 | 根拠 | 反証条件 |
|---|---|---|
| pCPU contention | vCPU wait、steal、host run queue が同時に増える | host に余力があり wait も増えていない |
| NUMA remote access | CPU placement と memory node が離れ、remote counter が増える | local placement でも同じ latency |
| storage saturation | guest と backend の queue / latency が同時に増える | backend latency が正常で QEMU だけ待つ |
| network queue drop | throughput 頭打ち時に queue と drop が増える | 全 interface の drop が増えていない |
| memory pressure | reclaim、fault、swap、memory PSI が増える | working set に余力があり pressure もない |
仮説に反証条件がないと、変更後に都合のよい metric だけを見ることになります。改善するはずの indicator と、悪化してはいけない indicator を先に決めます。
標準構成から段階的に制約を追加する
最初から passthrough や DPDK を選ばず、標準構成が SLO を満たすか確認します。性能を上げるために abstraction を減らすほど、migration、snapshot、sharing、monitoring、failure recovery の制約が増えます。
| 段階 | 選択肢 | 追加される主な制約 |
|---|---|---|
| 標準 | 共有 CPU、通常 page、virtio | scheduler と shared backend の競合 |
| 配置制御 | CPU pinning、numatune、HugePages | capacity、NUMA、移行先互換 |
| 処理分離 | IOThread、multiqueue、vhost-user | thread / queue affinity と監視 |
| device 直結 | SR-IOV、PCI Passthrough | migration、sharing、host visibility |
| 専用 dataplane | DPDK、poll mode | CPU 専有、HugePages、運用 tool |
上位段階が常に優れているわけではありません。必要な SLO を満たす最小の制約を選びます。
変更は 1 つずつ再検証する
| 段階 | 実施すること |
|---|---|
| 1 | SLO、workload、failure domain、baseline を記録する |
| 2 | metric から原因候補と反証条件を決める |
| 3 | XML、host 設定、application 設定の変更点を 1 つにする |
| 4 | 同じ workload、時間、sample 数で再測定する |
| 5 | 成功 indicator と副作用を比較する |
| 6 | 改善しなければ戻し、次の仮説へ進む |
CPU pinning、HugePages、queue 数、cache mode を同時に変えると、因果関係を追えません。変更に依存関係がある場合は、適用順序と各段階の測定点を決めます。
測定の再現性を確保する
- warm-up と本測定を分ける
- 同じ dataset、request、packet、block size を使う
- background job と co-tenant の条件を記録する
- 平均だけでなく分位点と sample 数を残す
- host、guest、backend の version と設定差分を保存する
- 複数回実行し、ばらつきと confidence を確認する
短い benchmark の最高値を採用せず、実運用に近い継続時間と peak 条件で比較します。低遅延 workload では、平均 throughput を維持していても p99 と jitter が悪化すれば不合格です。
performance result を decision record に残す
| 記録項目 | 内容 |
|---|---|
| 目的 | 改善する SLO と business / service 上の理由 |
| baseline | workload、metric、時間、topology、version |
| 仮説 | 原因、根拠、反証条件 |
| 変更 | XML、host、guest、application の差分 |
| 結果 | 成功 indicator、副作用、ばらつき |
| 判断 | 採用、保留、rollback と次の action |
結果だけでなく、採用しなかった理由も残します。将来 hardware、kernel、QEMU、workload が変わった際に、再評価すべき前提が分かります。
rollback を性能試験の一部にする
変更前の live / inactive XML、host topology、pool、affinity、queue、cache、network path を保存します。rollback 後に設定が戻っただけでなく、baseline の性能と運用機能を再現できるか確認します。
virsh dumpxml vm01
virsh dumpxml vm01 --inactive
virsh domstats vm01 --cpu-total --balloon --vcpu --interface --block --iothread --memory
virsh vcpupin vm01
virsh emulatorpin vm01
virsh numatune vm01
lscpu -e=CPU,NODE,SOCKET,CORE,ONLINE
numactl --hardware- p99、throughput、error が閾値を超えた場合の rollback
- VM 起動、restart、migration が失敗した場合の rollback
- 同居 VM や host service が悪化した場合の rollback
- 設定変更と workload 変更を別々に戻せること
- rollback 後の再測定を予定に含めること
よくある失敗
| 失敗 | 問題 | 修正 |
|---|---|---|
| CPU 使用率だけで判断する | I/O wait と pressure を見落とす | latency、queue、PSI を合わせる |
| 問題発生後だけ測る | 正常 baseline がない | 継続的に同じ metric を保存する |
| guest だけを見る | host と backend の競合を見落とす | resource path を対応付ける |
| 複数設定を同時に変える | 効果と副作用を分離できない | 1 変更 1 再測定にする |
| 最高値だけ採用する | ばらつきと tail latency を隠す | 複数回と分位点で比較する |
| 速くなれば完了にする | migration と recovery を失う | 運用 lifecycle も test する |
まとめ
VM パフォーマンス最適化は、個別の高速化技術を積み上げる作業ではありません。SLO と workload を定義し、guest から physical resource までを同じ時間窓で測り、utilization、pressure、queue、latency、throughput、error を対応付けます。
原因候補には根拠と反証条件を持たせ、変更を 1 つだけ適用して再測定します。改善量だけでなく migration、sharing、monitoring、recovery の制約と rollback を確認し、必要な SLO を満たす最小の変更を採用することが要点です。

