VPSベンチマークの正しい測り方と結果の読み方
まずyabs.shを実行し、fio、sysbench、iperf3で結果を検証します。CPU、メモリ、ディスク、回線の数値が何を意味するか、なぜ1回の測定では判断できないかを解説します。
VPS のベンチマークが意味すること
VPS のベンチマークでは、4 つの項目を測定します。単一の CPU コアの処理速度、マシンのメモリ帯域幅、ストレージが 1 秒あたりに処理できる小さなランダムディスク操作の数、そしてネットワーク回線が提供するスループットです。yabs.shを 1 回実行すると、約 10 分で CPU、ディスク、ネットワークの結果を取得できます。メモリ帯域幅については、以下の個別のテストを使用します。結果の読み取りのほうが難しい点に注意してください。VPS は他のテナントと物理ハードウェアを共有するため、同じマシンでも 03:00 には 1 つの値を示し、20:00 には大きく異なる値を示すことがあります。
ここでは、まず yabs.shを実行して概要を確認し、その後で内部で使用されるツールを手動で実行します。自分で実行すれば、1 つのフラグだけを変更して値の変化を確認し、その値が実際に何を測定していたのかを理解できます。これはマシンのセットアップ後に実施してください。セットアップ前には実施しないでください。新しい VPS で最初の 10 分に行う作業を先に実施します。初回の更新をまだ適用中のマシンでは、ハードウェアとは無関係の理由でベンチマーク結果が悪くなるためです。
測定する前にマシンを確認する
不正確なベンチマークの半分は、作成者がマシンの構成を理解していないことが原因です。
nproc
lscpu | grep -E 'Model name|Hypervisor|Thread'
free -h
df -hT /
uname -r
systemd-detect-virtHypervisor vendor: KVM は完全仮想化を意味するため、独自のカーネルを実行します。systemd-detect-virt に lxc または openvz と表示される場合は、コンテナ仮想化です。この場合、ホストのカーネルを共有し、CPU とメモリの制限は仮想ハードウェアではなく cgroup(control group)の設定になります。cgroup v2 のシステムでは、コンテナの cgroup から CPU 制限を確認できます。次のパスは、その cgroup が /sys/fs/cgroup にマウントされている場合に使用します。
cat /sys/fs/cgroup/cpu.maxmax 100000 は、この cgroup に独自の quota がないことを意味します。ただし、上位の cgroup が quota を設定することはあります。200000 100000 は、100000 マイクロ秒の各期間で 200000 マイクロ秒分の CPU を使用できることを意味します。これは 2 コア分の quota です。4 vCPU と宣伝されたプランでも、quota が 2 コア分なら、4 コア相当のスコアにはなりません。ベンチマークツールでこの制限を確認できます。VoxelBench は CPU quota を報告し、ホストがサーバーの利用可能数を大幅に上回る CPU を公開している場合、共有 CPU または throttled CPU であることを示します。
df -hT / は別の理由で重要です。Type 列に関係するためです。overlay と表示される場合はコンテナ内にいます。この場合、ディスクの結果は、その overlay の下にあるストレージの特性を示します。今のうちに確認しておいてください。
Steal time を常時監視する
Steal time は、ハイパーバイザーが仮想 CPU をスケジュールしなかったため、仮想 CPU が意図せず待機していた時間の割合です。利用できない CPU 時間を示す有用な指標ですが、近隣の仮想マシンが高負荷なのか、プロバイダーが CPU クォータを適用しているのかは区別できません。
vmstat 1 10右側の st 列を確認します。Steal time が継続して発生している場合、ゲストで CPU 時間を利用できなかったことを意味します。ただし、値が 5% を超えていても、ホストのリソースが過剰利用されているとは限りません。プロバイダーが CPU クォータの適用を steal time として表示することもあります。top には、CPU 行の %st と同じ値が表示されます。ベンチマーク中は、別の SSH セッションで vmstat 1 を実行し続け、各結果の横に steal の値を記録します。
yabs.sh から始める
yabs.sh (Yet Another Bench Script) は、fio、iperf3、Geekbench を実行して、1 つのサマリーを出力する shell script です。すでにインストールされている fio と iperf3 はそのまま使用し、未インストールの場合は static binary をダウンロードします。VPS のベンチマークに関する議論で共通して使われるため、yabs の出力は他の人と結果を比較する最も速い方法です。
プロジェクトが用意している one-line 形式は次のとおりです。
curl -sL yabs.sh | bashこれは、URL がその時点で返す内容をそのまま shell に渡します。いったんダウンロードして内容を確認してから実行してください。
curl -sLo yabs.sh https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh
less yabs.sh
bash yabs.shpipe で実行する場合は -s -- の後に flag を指定します。local copy を実行する場合は、filename の直後に指定します。主な flag は次のとおりです。-f は disk test を省略し、-i は network test を省略し、-g は Geekbench を省略します。-r は iperf3 の測定先を 3 か所に減らし、-j は結果を JSON で出力し、-w results.json はその JSON を file に書き込みます。
bash yabs.sh -r -w yabs-run1.json初回実行前に、2 点確認してください。Geekbench は結果を upload し、公開された browser.geekbench.com URL を出力します。そのため、その link を持つ人は誰でも CPU model と score を確認できます。-g を指定すると、この test を完全に省略できます。もう 1 点は、iperf3 stage で複数の region にある server へ実際の network traffic を送信することです。この通信量は月間 bandwidth allowance に計上されます。1 Gbit/s の link では、network stage 全体で数十 GB を転送することがあります。allowance が少ない場合は -r、従量課金の link では -i を使用してください。
yabs の出力の各項目の意味
ディスクセクションでは、4k、64k、512k、1m の4つのブロックサイズで、読み取りと書き込みを50/50で混在させて fio を実行します。それぞれについて、IOPS(1秒あたりの入出力処理数)と帯域幅を報告します。データベース、メールサーバー、または小さな書き込みを大量に処理するシステムでは、4k の行を確認します。ほとんどのサーバー IO は小さく、分散しているためです。バックアップや動画では、連続した大量のバイトを転送するため、1m の行を確認します。
ネットワークセクションでは、複数のリージョンにある公開サーバーに対して、両方向で並列ストリームを使用して iperf3 を実行します。ここで低い数値が出ても、すぐに結論を出さず、確認が必要な結果として扱います。公開 iperf3 サーバーは共有されており、飽和していることも多いためです。結果が悪い原因は、接続先にある可能性があります。
Geekbench セクションでは、シングルコアスコアとマルチコアスコアを示します。シングルコアスコアは、1つのリクエスト、1回のコンパイル、または1つのクエリが完了する速度の目安になります。マルチコアスコアは主に、実際に割り当てられたコア数を示します。
Disk: fioを自分で実行する
fio(flexible IO tester)は、yabsのディスクセクションで使用される基盤ツールです。直接実行すると、各フラグの意味が明確になります。
sudo apt update && sudo apt install -y fio sysbench iperf3実際に使用するファイルシステム上で、キュー深度32の4kランダム読み取りテストを実行します。
fio --name=randread4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randread --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reporting出力から読み取るサマリー行は次のようになります。
read: IOPS=184k, BW=719MiB/s (754MB/s)(42.1GiB/60001msec)その下で、fioはclat percentilesブロックを出力します。引用する価値があるのは99.00パーセンタイルです。100件中で最も遅い1件のリクエストが待機した時間を示すためです。平均レイテンシでは、ユーザーが実際に気付く停止時間が隠れます。
--direct=1はO_DIRECTでファイルを開くため、読み取りはkernel page cacheを経由しません。これを指定しない場合、RAMが8Gあるマシンで2Gファイルを2回目に読み取ると、メモリから処理され、fioはIOPSを数百万と報告します。その数値は実在しますが、メモリの性能を示しています。--ioengine=libaioは非同期リクエストを送信します。これにより、--iodepth=32は32件をin flightに維持できます。psyncのような同期engineでは、iodepthを1より大きくしても何も起きません。そのため、1件ずつリクエストを測定することになります。--time_based --runtime=60は処理量を固定する代わりに、60秒間実行します。これにより、高速なディスクと低速なディスクで同じwall clock時間になり、比較が公平になります。--size=2Gはテストファイルのサイズを設定します。パス上にあるすべてのcacheより大きくし、先に空き容量があることを確認してください。
ランダム書き込みでは、同じコマンドに--rw=randwriteを指定します。別々に実行し、その後でファイルを削除してください。
fio --name=randwrite4k --filename=./fio-testfile --size=2G --bs=4k \
--rw=randwrite --ioengine=libaio --iodepth=32 --direct=1 \
--runtime=60 --time_based --group_reporting
rm -f ./fio-testfile実際のトラフィックに近い混合処理には、--rw=randrw --rwmixread=70を使用します。使用しているストレージの種類による結果の差は、どのフラグによる差よりも大きくなります。この違いについては、VPSのNVMeストレージとSATA SSDストレージの違いで説明しています。
fio が Unknown error -1 で停止する場合
すべてのファイルシステムで Direct IO を利用できるわけではありません。そのため、--direct=1 を設定した fio が最初のリクエストで失敗する場合は、まず Direct IO を切り分けます。失敗時の表示は次のようになります。
fio: io_u error on file ./fio-testfile: Unknown error -1: read offset=0, buflen=4096
fio: pid=1234, err=-1/file:ioengines.c:321, func=get_events, error=Unknown error -1最初に df -hT . を実行します。Docker がコンテナにデフォルトで割り当てる Type である overlay 自体は、原因ではありません。overlayfs は O_DIRECT を下位のファイルシステムへ渡し、そのファイルシステムが Direct IO に対応していない場合にのみ拒否します。そのため、ext4 または xfs 上の overlay では --direct=1 --ioengine=libaio が動作します。テストファイルの下位にあるファイルシステムが Direct IO に対応していない場合、fio は通常、ファイルを開く時点でそのことを示します。表示は fio: looks like your file system does not support direct=1/buffered=0 です。その場合は、--filename を bind mount したボリュームなどの実際のローカルストレージ上のパスに設定するか、コンテナ内ではなくホスト上で fio を実行します。実ストレージを利用できない場合でも、バッファリングされた同期実行を行えば、少なくともコマンド自体が正しいことを確認できます。
fio --name=randread4k-buffered --filename=./fio-testfile --size=256M --bs=4k \
--rw=randread --ioengine=psync --direct=0 --numjobs=1 \
--runtime=15 --time_based --group_reporting
rm -f ./fio-testfileこの実行結果が何を示すかを正しく理解してください。最初の実行後は 256M のファイルが page cache に残るため、IOPS の値は RAM の性能を示します。fio がインストールされており、フラグを解釈できることの確認には使用できます。ディスクの結果として引用してはいけません。
dd はディスクベンチマークではありません
dd は多くの VPS スレッドで使われていますが、答えられるのは限定された 1 つの問いだけです。
dd if=/dev/zero of=./ddtest bs=1M count=1024 oflag=direct conv=fdatasync
rm -f ./ddtestこれは、1 スレッドで 1 件のリクエストだけを処理した場合のシーケンシャル書き込みスループットを測定します。簡易的な確認としては妥当です。ただし、ランダム IO については何も分かりません。また、32 件のリクエストが同時に到着した場合の動作も分かりません。oflag=direct を外すと、書き込みはページキャッシュを経由します。それでも conv=fdatasync によって、コマンドが終了する前に出力データがストレージへ書き込まれます。これも外すと、結果の大部分は、カーネルが書き込みをメモリに受け入れる速さを測るだけになります。そのため、フォーラムの投稿に記載された dd の値は、しばしば現実離れしたものになります。
CPU: sysbench cpu
sysbench cpu --cpu-max-prime=20000 --threads=1 run
sysbench cpu --cpu-max-prime=20000 --threads=$(nproc) run確認すべき数値は events per second です。まずシングルスレッドで実行します。この数値は、1 件の PHP リクエストが完了する速さや、1 件のコンパイルジョブが完了する速さを左右します。同じ価格帯のホスト間で最も差が出やすい数値でもあります。次に、すべてのスレッドを使用して実行します。割り当てられた vCPU 全体でスループットがどのように伸びるかを確認できます。
このテストが測定する内容を明確に理解してください。sysbench cpu は、試し割りによって素数を繰り返し求めます。各候補について倍精度の平方根を求め、その浮動小数点の上限と各除数を比較しながら、64 ビット整数の剰余で除数を検査します。そのため、整数演算と浮動小数点演算が混在します。実際のワークロードに近い形でメモリ帯域幅、ベクトル演算ユニット、キャッシュを負荷するテストではありません。2 台のホストを順位付けする用途には適していますが、アプリケーションの実行性能を予測する用途には適していません。
Ubuntu 24.04 には sysbench 1.0.20 が含まれており、テスト名を先に指定します。古い記事にある --test=cpu 付きのコマンドをコピーすると、WARNING: the --test option is deprecated になります。sysbench 0.4 と sysbench 1.0 のスコアはまったく比較できません。そのため、バージョンが明記されていない公開値を基準にして、自分の環境を評価しないでください。
メモリ: sysbench memory
sysbench memory --memory-block-size=1M --memory-total-size=20G --memory-oper=write --threads=1 run
sysbench memory --memory-block-size=1M --memory-total-size=20G --memory-oper=read --threads=1 run結果は MiB/sec です。--memory-block-size は 1M のままにし、比較するすべてのホストで同一にしてください。1K では、操作ごとのオーバーヘッドが 1000 倍の頻度で発生するため、数値が大幅に低下します。その結果、メモリ帯域幅ではなく、ループのコストを測定することになります。公開されているメモリスコアで、最も不一致が多いフラグです。
ネットワーク: iperf3
スループットを正確にテストするには、自分が管理する別のマシンを相手にします。両端で何が実行されているかを把握できるためです。
相手側で次を実行します。
iperf3 -sTCP 5201で待ち受けます。テスト元のアドレスに対してのみポートを開き、終了したら閉じてください。VPSでの基本的なufwファイアウォールルールで構文を説明しています。
テスト対象のVPSから次を実行します。
iperf3 -c 203.0.113.10 -t 30
iperf3 -c 203.0.113.10 -t 30 -R
iperf3 -c 203.0.113.10 -t 30 -P 8最初のコマンドは、テスト対象マシンからのアップロードを測定します。-Rは方向を反転し、ダウンロードを測定します。-P 8は8本の並列ストリームを開きます。
単一ストリームと並列版の両方を実行してください。両者は異なる点を確認するためです。1本のTCP接続で保持できる未確認応答データ量は、ウィンドウサイズが許容する範囲に限られます。そのため上限は、おおよそウィンドウサイズを往復遅延時間で割った値です。遅延が80 msでウィンドウが4 MBの場合、基礎となるリンクがどれほど高速でも、上限は約400 Mbit/sです。単一ストリームの値から、1回のダウンロードで得られる速度が分かります。並列実行の値から、リンクの容量が分かります。
実行中は、帯域幅の使用許容量を確認してください。1 Gbit/sで30秒間実行すると約3.75 GB転送されます。各方向で複数回実行することになります。
参照値と自分の結果の読み方
このグラフのデータ
[
{
"device": "Local NVMe",
"iops_4k_read": "180,000"
},
{
"device": "Local SATA SSD",
"iops_4k_read": "90,000"
},
{
"device": "Network block",
"iops_4k_read": "12,000"
},
{
"device": "Spinning disk",
"iops_4k_read": "180"
}
]公開されている結果では、ローカル NVMe ボリュームは通常、4k ランダム読み取りで 180,000 IOPS 前後です。ローカル SATA SSD は 90,000 前後です。ネットワーク接続型のブロックストレージは、各リクエストがディスクに到達する前にネットワークを経由するため、12,000 前後になります。回転ディスクは、ランダムリクエストごとに物理ヘッドを移動するため、おおむね 180 です。
これらは各ストレージクラスについて公開されている一般的な値であり、1 台のホストで測定した結果ではありません。用途は、自分の測定結果が同程度の桁に収まっているかを確認することです。NVMe として販売されているプランで 4k IOPS が数千程度しか出ない場合は、まず --direct=1 が有効だったか確認してください。有効だった場合は、ストレージの競合や表示されているハードウェアに加えて、そのプランの IOPS 上限とバーストクレジットを確認します。
1 回の実行はベンチマークではない
1 回の結果は、共有マシン上の 1 分間を切り取ったスナップショットです。1 サンプルとして扱ってください。
- すべてのテストを少なくとも 5 回実行し、異なる時間帯と少なくとも 2 日に分散させます。中央値とばらつきを記録してください。ばらつきを示さずに公開された結果は、マーケティング用の数値です。
- 各実行の横に steal time を記録します。
stが高かった実行も残し、それが競合を示すのか、プランの CPU quota を示すのかを調べてください。これらを除外すると、実際に得られる性能を隠すことがあります。 - ディスクテストは 2 つの実行時間で行います。多くのプランでは、時間の経過とともに補充される burst IOPS の許容量が設定されています。しかし、60 秒間の fio 実行も
--runtime=600も、性能の下限を測定したことを保証しません。AWS gp2 の credits は、残高が満タンであれば少なくとも 30 分間 3,000 IOPS を維持できます。そのため、どちらの実行も burst performance を測定する可能性があります。結果を sustained performance と判断する前に、プロバイダーの credit model を確認し、credit balance を監視してください。 - ほかに何も実行されていないことを確認します。CPU テストの途中で
unattended-upgradesが apt transaction を開始すると、実際のスコアが下がります。各実行の前にps -e -o comm= | grep -E 'apt|dpkg'を行えば、1 秒で済みます。 - 一度に変更する変数は 1 つだけにします。ツールのバージョン、block size、thread count が異なると、どれほど似た数値に見えても比較できません。
2 つのプロバイダーを比較する場合は、同じ日の同じ時間帯に実行してください。そうしないと、測定しているのは時間帯です。
自分のワークロードを最後にベンチマークする
合成ベンチマークツールはマシンを順位付けします。マシンが十分かどうかを判断できるのは、自分のワークロードだけです。実際に行う処理の時間を測定してください。
time tar -czf /tmp/bench.tgz /usr/share
rm -f /tmp/bench.tgzこれは数百MBを圧縮するため、CPUとディスクを同時に使用します。そのため、どちらかが変わると結果も変わります。Removing leading / from member names の警告は正常です。さらに良い方法は、自分のビルド、自分の最も遅いクエリ、または自分のページレンダリングの時間を測定することです。あるホストで4分、別のホストで7分かかるビルドなら、Geekbenchの評価に関係なく結論は明らかです。これは、より高性能なマシンに費用をかけても効果がなくなる時点を判断するための測定でもあります。VPSの実際の月額を確認したり、ワークロードを専用サーバーへ移行したりする前に知っておく価値があります。
FAQ
実行するたびにベンチマーク結果が変わるのはなぜですか?
VPS は他のテナントと物理 CPU、ストレージ、ネットワークを共有するため、その時点で他のテナントが何をしているかによって結果が変わります。テスト中に vmstat 1 を実行し、st 列を確認してください。継続的な steal time は利用できなかった CPU 時間を記録しますが、ホスト側の競合だけでなく、プロバイダーが購入した CPU 割り当てを適用している影響も含む場合があります。5% を超えていても、原因が確定するわけではありません。必要なのはチューニングではなく、測定方法の見直しです。時間帯を変えて各テストを 5 回以上実行し、ばらつきとともに中央値を報告してください。
fio が数百万 IOPS を報告するのはなぜですか?
ほとんどの場合、--direct=1 が指定されていないためです。これがないと fio は kernel page cache 経由で読み取るため、最初の pass の後は 2G のテストファイルが RAM から提供され、測定しているのはメモリ帯域幅になります。--direct=1 を追加し、テストファイルは経路上のどの cache よりも大きくしてください。--direct=1 が失敗する場合は、df -hT . を実行して、テストファイルがどのストレージ上にあるかを確認してください。overlay type であること自体は問題ではありません。overlayfs は O_DIRECT を下層のストレージへ通過させるためです。下層の filesystem が direct IO を拒否する場合に限り、テストファイルを実際の local storage に移してください。
yabs.sh だけで十分ですか?
最初の確認には十分です。4 種類の block size で fio を実行し、両方向で iperf3 を実行して、他の人も読めるサマリーを 1 つ出力します。ただし、数値の理由を調べたい場合は不十分です。テストごとに flag を変更できないためです。yabs の結果に不自然な点があれば、fio または sysbench を直接実行して再現し、1 回に 1 つの flag だけを変更してください。
アプリケーションの体感を予測する単一の数値はどれですか?
ほとんどの Web およびデータベースのワークロードでは、順に single core の CPU 速度と 4k random read latency です。一般的なリクエストは小さいため、throughput の数値は目立つものの、結果を左右することはほとんどありません。平均値ではなく、fio の clat percentiles block から 99th percentile を示してください。100 回に 1 回の遅いリクエストをユーザーが体感するためです。
ベンチマークの前に何かをインストールする必要がありますか?
fio、sysbench、iperf3 はすべて Ubuntu と Debian の archives に含まれています。sudo apt install -y fio sysbench iperf3。yabs.sh は Bash で実行され、ダウンロードには curl または wget、Geekbench の展開には tar が必要です。tar がない場合、Geekbench はスキップされます。インストール済みであれば fio と iperf3 を使用し、見つからない場合は static binary をダウンロードします。完了したら、すべてのテストファイルを削除してください。20G のディスクに 2G の fio ファイルを残すと、数週間後に誰かの disk full alert の原因になるためです。