hidemium's blog

日々学んだことをアウトプットする。

ESXiのCPUスケジューリングについてまとめてみた

vSphere環境を使っていて、仮想マシンのvCPUのサイジングについてベストプラクティスがいくつかありますが、そういう背景がどういったところにあるのか、ベストプラクティスから外れた場合にどうなるのか書いてみようと思います。

構成

  • vCenter 7.0 U3
  • ESXi 7.0 Update 3
  • Intel NUC NUC7i3BNH
    • Intel(R) Core(TM) i3-7100U CPU @ 2.40GHz
  • Ubuntu 22.04

よくありそうな疑問

仮想マシンのvCPUのサイジングとして、以下のものがあります。

  • 一般的なベストプラクティスとして、ハイパースレッディングが有効な環境で仮想マシンのvCPU数は物理コア数を超えないようにする

vSphereの設定として、仮想マシンのvCPUは、ハイパースレッディングが有効な場合、仮想マシンのvCPU数は論理コア数まで設定することが可能です。例えば、物理コアが24コアあった場合は、48vCPUまで設定することが可能です。

仮想マシンのvCPUを物理コアを超えた場合にどのようなことが起きるのか見ていこうと思います。

CPUスケジューリングについて

仮想マシンのvCPUがどの物理コアに割り当てされるかは、CPUスケジューラーが担っています。

複数vCPUを持った仮想マシン(SMP VM)の場合、仮想マシン内で実行されているゲスト OS とアプリケーションを、専用の物理マルチプロセッサ上で実行されているかのように見せており、ESXiが同期ケジューリングをサポートすることで実装しています。

ゲストOSは管理するすべてのプロセッサがほぼ同じ速度で実行されることを前提としています。ただし、仮想化環境では、ゲストOSによって管理されるプロセッサは、実際にはハイパーバイザーによってスケジュールされた仮想CPUであるため、複数の仮想マシン間で物理プロセッサをタイム スライスして利用しています。

Strict co-scheduling

ESX 2.xで実装されたアルゴリズムで、vCPUごとににスキューと呼ばれるずれが発生すると、さらなるスキューを防ぐために、同じ仮想マシン内のすべてのvCPUが強制的にスケジュール解除 (「同時停止」(co-stop)) されます。スキューが検出された後はすべての vCPUを同時にスケジュールする必要があるため、このアプローチは厳密な同期ケジューリングと呼ばれています。

Relaxed co-scheduling

ESX 3.xからStrict co-schedulingに代わって、Relaxed co-schedulingというアルゴリズムが実装されました.

すべてのvCPUに同期を求めるのではなく、処理を実行しているvCPUのみについてのみ同期を行う仕組みに変更されています。

ハイパースレッディングについて

ハイパースレッディングは、1つのプロセッサ上で2つスレッドからの命令を同時に実行できるようにすることで、物理的なCPU性能を向上させる技術です。

この技術により、スレッドレベルの並列処理により性能を向上させることができますが、計算リソースの総量は依然として1つの物理プロセッサが上限となります。

どの程度性能が向上するかは、処理内容によって変わり、性能が2倍になるわけではなく、1.2倍程度といわれています。

ハイパースレッディングによりアイドル リソースを有効に活用することによってパフォーマンスを向上でき、特定の重要なワークロード タイプについてスループットを向上させます。

ESXi ホストは、プロセッサ時間をインテリジェントに管理して、システム内のプロセッサ コア間で負荷が円滑に分散されるように保証します。CPU 0 と 1 はともに第 1 のコア上にあり、CPU 2 と 3 は第 2 のコア上にあるといったように、同じコア上の論理プロセッサは、連続した CPU 番号を持ちます。

仮想マシンは、同じコアの 2 つの論理プロセッサ上よりも、2 つの異なるコア上に優先的にスケジュール設定されます。

仮想マシンのvCPUを物理コアと一致した場合、物理コアを超えた場合の挙動

物理コアが2コア、ハイパースレッディングオンで4スレッドのサーバーで、仮想マシンAにはvCPU 2、仮想マシンBにはvCPU4を割り当てて、負荷ツールを実行して、挙動を確認してみます。

stressコマンド

まずは、stressコマンドですべてのvCPUに負荷をかけてみます。

2vCPUの場合、CPU使用率が高いコアはCPU番号がずれているため、2つの異なる物理コアでスケジューリングされていることが分かります。

4vCPUの場合、各コアの使用率は50%で止まっていることが分かります。

仮想マシン 物理ホストのクロック数(Mhz) 物理ホストのCPU使用率 CPU 0使用率(Core 1) CPU 1使用率(Core 1) CPU 2使用率(Core 2) CPU 3使用率(Core 2)
仮想マシンA(vCPU2) 4.7 100% 98% 2% 98% 2%
仮想マシンB(vCPU4) 4.7 100% 50% 50% 50% 50%

仮想マシンの観点で見ると、2vCPUの場合は、各コアのクロック数は物理クロック数と一致していますが、4vCPUの場合、各コアのクロック数は物理クロック数より小さい値になっていることが分かります。

4vCPUでは、仮想マシン全体のクロック数は、物理ホストのクロック数を超えて表示されていますが、実際の物理ホストのクロック数は変わらない状態となっています。

また、4vCPUでは、仮想マシンのCPU使用率は61%で止まっていることが分かります。

仮想マシン 仮想マシンのCPU使用率 仮想マシンのクロック数(Mhz) vCPU 0クロック数(Mhz) vCPU 1クロック数(Mhz) vCPU 2クロック数(Mhz) vCPU 3クロック数(Mhz)
仮想マシンA(vCPU2) 98% 4.7 2.35 - 2.35 -
仮想マシンB(vCPU4) 61% 5.9 1.47 1.47 1.47 1.47

pgbench

DBのベンチマークツールを実行して処理性能の比較をしてみようと思います。

PostgreSQLをインストールし、ベンチマークで使うでDBの作成とデータセットの初期化を行います。

$ sudo install postgresql postgresql-client postgresql-contrib
$ sudo -u postgres createdb test
$ sudo -u postgres pgbench -i -s 10 test

vCPU2とvCPU4の仮想マシンごとにベンチマークの取得を行います。

$ sudo -u postgres pgbench -c 16 -t 1000 test

各vCPUごとにベンチマークを取得してみましたが、vCPU4のほうが高い状態となりました。

これは、ハイパースレッディングにより、各コアでの性能が十分になくても、並列処理を行う場合は、パフォーマンスが出やすいことを示していそうです。

仮想マシン TPS
仮想マシンA(vCPU2) 2288
仮想マシンB(vCPU4) 3248

まとめ

試してみた内容についてまとめると以下のようなことになりそうです。

  • ハイパースレッディングが有効な環境で仮想マシンのvCPU数は物理コア数を超えると、物理ホストのCPU使用率は100%で頭打ちとなる
  • ハイパースレッディングが有効な環境で仮想マシンのvCPU数は物理コア数を超えると、並列処理を行う場合は、パフォーマンスを出しやすい
  • 仮想マシンが複数台あると、co-stopが発生しやすくなるため、物理ホスト上の仮想マシンは少なくしたほうがよいかもしれない

参考