ぱと隊長日誌

ブログ運用もエンジニアとしての生き方も模索中

Hyper-V のルートスケジューラで他の VM の存在は仮想プロセッサのパフォーマンスにどれだけ影響するのか?

概要

Windows 10 の Hyper-V ではデフォルトのスケジューラが「ルートスケジューラ」となっています。このスケジューラは以下の説明がなされています。

ルート スケジューラの種類が有効になっている場合、ハイパーバイザーがルート パーティションに対する作業スケジュールの渡しを制御します。 ルート パーティションの OS インスタンスの NT スケジューラが、システム LP に対する実行スケジュール機能のすべての側面を管理します。

Hyper-V Hypervisor のさまざまな種類のスケジューラを理解して使用する | Microsoft Learn

Windows のスケジュールモデルについては以下の説明があります。

システムは、同じ優先順位を持つすべてのスレッドを等しいものとして扱います。 システムは、優先順位が最も高いすべてのスレッドにラウンドロビン方式でタイム スライスを割り当てます。 これらのスレッドのいずれも実行する準備ができていない場合、システムはラウンドロビン方式でタイム スライスを次に優先度の高いすべてのスレッドに割り当てます。 優先度の高いスレッドを実行できるようになると、システムは優先順位の低いスレッドの実行を停止し (タイム スライスの使用を終了せずに)、優先度の高いスレッドに完全なタイム スライスを割り当てます。

優先度のスケジュール設定 - Win32 apps | Microsoft Learn

この2つの説明を踏まえると、「ルートスケジューラ」について以下のことが想定されます。

  • ラウンドロビン方式のスケジュールモデルになる。
  • 仮想プロセッサ (VP) がなすべき仕事を持たなければ、タイムスライスの割り当てはない(オーバーヘッド分のみ)。

この想定が妥当であるかを検証しました。

検証環境

ホスト

プロセッサ Intel Core i5-6600 CPU @ 3.30GHz ※ 4 コアのCPUです
OS Windows 10 Pro バージョン 21H2
VM1
構成バージョン 9.2
プロセッサ 1 or 4 個の仮想プロセッサ
OS Red Hat Enterprise Linux release 8.7
VM2
構成バージョン 9.2
プロセッサ 4 個の仮想プロセッサ
OS Red Hat Enterprise Linux release 9.1

VM1 / VM2 で OS のバージョンは異なりますが、今回の検証には影響しないと想定しています。VM のスケジュールを管理するのはハイパーバイザーだからです。

検証

VM1 で sysbench を実行します。この sysbench の "events per second" でパフォーマンスへの影響を評価します。

-- 4 スレッドでの実行の場合
# sysbench --threads=4 --test=cpu run

VM 2 で stress-ng を実行します。これで他の VM による影響をシミュレーションします。

-- 3 CPU に 100% の負荷をかける場合
# stress-ng -c 3 -l 100

まず、VM1 だけを起動したときの測定結果を示します。ここでは VM1 の VP を 1 個にした時の結果も掲載します。

条件 パフォーマンス
1 VP - 1 スレッド 1271.76
4 VP - 1 スレッド 1271.18
4 VP - 4 スレッド 4682.52

VP の数による差異は微々たるものでした。

次に、VM2 を起動だけします(stress-ng を実行しない)。この時の VM1 での測定結果です。

条件 パフォーマンス
4 VP - 1 スレッド 1263.94
4 VP - 4 スレッド 4665.39

VM1 を単独起動したときと比べ、ほとんど差異はありませんでした。このことから、仕事のない VM に対してはタイムスライスが与えられないとわかります。

VM2 で 3 VP に対して 100% の負荷をかけます。この時の VM1 での測定結果です。

条件 パフォーマンス
4 VP - 1 スレッド 1152.60
4 VP - 4 スレッド 2627.75

1 スレッドの時は VM2 が何もしない時と比べ、パフォーマンスが若干低下した程度の結果となりました。物理 CPU が 4 コアなので、VM2 で 3 コア分占有されても、残りの 1 コアを利用可能だったためと思われます。

4 スレッドの時は VM2 が何もしない時と比べ、パフォーマンスが 56% 程度に低下しました。VM1 が 4 VP、VM2 が 3 VP フル稼働したと考えると、各 VM に与えられたタイムスライスの割合を以下のとおり推測できます。
物理コア数 / 稼働 VP 数 = 4 / (4 + 3) = 57%
これは低下したパフォーマンスの割合とほぼ同じです。

VM2 で 4 VP に対して 100% の負荷をかけます。この時の VM1 での測定結果です。

条件 パフォーマンス
4 VP - 1 スレッド 924.82
4 VP - 4 スレッド 2301.64

1 スレッドの時は VM2 が何もしない時と比べ、パフォーマンスが 73% 程度に低下しました。4 スレッドの時は VM2 が何もしない時と比べ、パフォーマンスが 49% 程度に低下しました。

先ほどと同様に各 VM に与えられたタイムスライスの割合を計算してみます。
VM1 が 1 スレッドの時:
物理コア数 / 稼働 VP 数 = 4 / (1 + 4) = 80%
VM1 が 4 スレッドの時:
物理コア数 / 稼働 VP 数 = 4 / (4 + 4) = 50%

VM1 が 1 スレッドの時の計算と実測に若干の差異が見られます。VM2 で 3 VP に対して 100% の負荷をかけた時にも 1 スレッドだとパフォーマンスが若干低下していたので、何かしらのオーバーヘッドがあったのかもしれません。

VM1 が 4 スレッドの時は計算と実測がほぼ一致しました。

まとめ

ルートスケジューラのスケジュールモデルに対する想定が妥当であることを確認できました。また、重みづけの設定をしなければ、タイムスライスは稼働している各 VP に対して均等に割り当てられることもわかりました。

Hyper-V で論理プロセッサの利用状況は環境やワークロードに左右される

概要

Hyper-V の仮想プロセッサ (VP) と論理プロセッサ (LP) の対応について、マニュアルの記述を引用します。

  • ルート パーティションの各仮想プロセッサ (VP) は、論理プロセッサ (LP) に 1:1 でマップされます。 ホストの VP は、常に同じ基盤の LP で実行されます。ルート パーティションの VP の移行は必要ありません。
  • 既定では、ホスト VP を実行する LP は、ゲスト VP も実行できます。
  • ゲスト VP を使用可能な任意の論理プロセッサ上で実行するようにハイパーバイザーがスケジュールする場合があります。 ゲスト VP をスケジュールする際、ハイパーバイザー スケジューラは、一次キャッシュの局所性、NUMA トポロジ、およびその他のさまざまな要因を考慮する必要があります。最終的には、VP はいずれのホスト LP でもスケジュールされる可能性があります。
Hyper-V Hypervisor のさまざまな種類のスケジューラを理解して使用する | Microsoft Learn

ルートパーティションは VP と LP が 1:1 で対応するとあります。一方、ゲストOS では VP と LP の対応が動的に変化することを示唆しています。

ゲスト OS での VP / LP の対応について、環境やワークロードを変えて検証してみました。その結果、環境やワークロードによって LP の利用状況の傾向に違いがみられました。

検証環境

検証環境 1

ホスト
プロセッサ Intel Core i5-6600 CPU @ 3.30GHz ※ 4 コアのCPUです
OS Windows 10 Pro バージョン 21H2
Hyper-V
構成バージョン 9.2
プロセッサ 4個の仮想プロセッサ
OS Red Hat Enterprise Linux release 9.1

検証環境 2

ホスト
プロセッサ AMD A10-5800K ※ 4 コアのCPUです
OS Windows 10 Pro バージョン 21H2
Hyper-V
構成バージョン 9.2
プロセッサ 4個の仮想プロセッサ
OS Red Hat Enterprise Linux release 9.1

検証内容

LP の使用率をパフォーマンスモニターで確認しました。
オブジェクト:Hyper-V Hypervisor Logical Processor
カウンター:% Total Run Time
インスタンス:Hv LP 0-3(計 4 個)

また、異なる検証環境で LP の利用状況の傾向に違いがあるかを確認しました。

ストレステストを単一 VP で実行

CPU 0 (VP に相当)に対してストレステストを実行します。

# taskset -c 0 stress-ng -c 1 -l 100

検証環境1でCPU0にストレステスト
<検証環境 1>

検証環境2でCPU0にストレステスト
<検証環境 2>

検証環境 1 で 07:58:58 頃から実行しました。全ての LP (LP 0-3) でまんべんなく使用率が上がっています。

検証環境 2 で 08:49:24 頃から実行しました。LP の 使用率が LP0, LP1 に偏って見えます。

いずれにせよ、ゲスト OS の VP が LP と 1:1 で対応していない、ということが分かります。

Apache HTTP Server と Apache Bench を単一 VP で実行

CPU 0 で Apache HTTP Server と Apache Bench を実行します。

# taskset -c 0 httpd -k start
# taskset -c 0 ab -c 1 -n 1000000 http://localhost/

検証環境1でCPU0にApacheとベンチマーク
<検証環境 1>

検証環境2でCPU0にApacheとベンチマーク
<検証環境 2>

検証環境 1 で 07:41:55 頃から実行しました。全ての LP (LP 0-3) で使用率がまんべんなく上がっています。

検証環境 2 で 08:16:27 頃から実行しました。LP の 使用率が LP0, LP1 に偏って見えます。

Apache HTTP Server と Apache Bench を異なる VP で実行

CPU 0 で Apache HTTP Server、CPU 1 で Apache Bench を実行します。

# taskset -c 0 httpd -k start
# taskset -c 1 ab -c 1 -n 1000000 http://localhost/

検証環境1でCPU0にApacheとCPU1にベンチマーク
<検証環境 1>

検証環境2でCPU0にApacheとCPU1にベンチマーク
<検証環境 2>

検証環境 1 で 07:49:07 頃から実行しました。2つの LP (LP0, LP1) で使用率が増加し、残りの LP (LP2, LP3) はあまり変化がありませんでした。

検証環境 2 で 08:06:58 頃から実行しました。2つの LP (LP0, LP3) で使用率が増加し、残りの LP (LP1, LP2) は使用率が多少上がった程度でした。

検証補足

例示した検証結果では検証環境 2 で LP の使用率に偏りが見られました。ですが、別日に測定すると偏りが減っていることもありました。よって、測定時点の状況によって傾向に違いが出る可能性もありそうです。

まとめ

Hyper-V のゲスト OS では VP / LP の対応が動的に決定することを検証からも裏付けました。

また、LP の利用状況は環境やワークロードによって左右されることが分かりました。これはマニュアルの『ゲスト VP をスケジュールする際、ハイパーバイザー スケジューラは、一次キャッシュの局所性、NUMA トポロジ、およびその他のさまざまな要因を考慮する必要があります。』という記述に対応した挙動と考えられます。

クライアントシステムでも Hyper-V のハイパーバイザースケジューラを変更できる

クライアントシステムの Hyper-V のハイパーバイザースケジューラとして「ルートスケジューラ」のみサポートされます。

クライアント システムでのルート スケジューラの使用
Windows 10 バージョン1803以降、クライアント システムではルート スケジューラが既定で使用されます。クライアント システムでは、ハイパーバイザーを有効にすると、仮想化ベースのセキュリティと WDAG ワークロードの分離がサポートされ、異種のコア アーキテクチャを使用する今後のシステムを適切に運用できます。 これは、クライアント システムでサポートされる唯一のハイパーバイザー スケジューラの構成です。 管理者は Windows 10 クライアント システムで既定のハイパーバイザー スケジューラの種類を上書きすべきではありません。

Hyper-V Hypervisor のさまざまな種類のスケジューラを理解して使用する | Microsoft Learn

ですが、クライアントシステムでも Hyper-V のハイパーバイザースケジューラの設定をすることは可能です。設定方法を引用します。

To select a scheduler type, open a command prompt with administrator privileges:

bcdedit /set hypervisorschedulertype type

Where type is one of:
Classic
Core
Root

The system must be rebooted for any changes to the hypervisor scheduler type to take effect.

Understanding and using Hyper-V hypervisor scheduler types | Microsoft Learn

ハイパーバイザースケジューラの設定変更を以下の環境で試しました。

プロセッサ AMD A10-5800K
OS Windows 10 Pro バージョン 21H2

ハイパーバイザースケジューラとして「従来のスケジューラ」を設定します。

PS > bcdedit /set hypervisorschedulertype Classic
この操作を正しく終了しました。

再起動後、現在のハイパーバイザースケジューラの種類判定を行います。

PS > Get-WinEvent -FilterHashTable @{ProviderName="Microsoft-Windows-Hyper-V-Hypervisor"; ID=2} -MaxEvents 1

   ProviderName: Microsoft-Windows-Hyper-V-Hypervisor

TimeCreated                      Id LevelDisplayName Message
-----------                      -- ---------------- -------
2022/11/17 20:23:13               2 情報             Hypervisor scheduler type is 0x1.

ハイパーバイザー起動イベント ID 2 は、次のとおりのハイパーバイザー スケジューラの種類の情報を提供します。

  • 1 = 従来のスケジューラ、SMT は無効化
  • 2 = 従来のスケジューラ
  • 3 = コア スケジューラ
  • 4 = ルート スケジューラ
Hyper-V Hypervisor のさまざまな種類のスケジューラを理解して使用する | Microsoft Learn

「従来のスケジューラ、SMT は無効化」が選択されたことを確認できました。

なお、今回の環境だと「コア スケジューラ」を設定しても「従来のスケジューラ、SMT は無効化」が選択されてしまいました。

マニュアルには以下の記載があります。

ハイパーバイザーのコア スケジューラは、Windows Server 2016 および Windows 10 バージョン1607 で導入された従来のスケジューラ ロジックに代わる新しい手段です。

Hyper-V Hypervisor のさまざまな種類のスケジューラを理解して使用する | Microsoft Learn

よって、Windows 10 だから利用できないというわけではなさそうです。

マニュアルには以下の記載もありました。

ホストの SMT が無効になっているコア スケジューラの動作
ハイパーバイザーがコア スケジューラの種類を使用するように構成されているにもかかわらず、SMT 機能が無効になっているか、仮想化ホスト上に存在しない場合、ハイパーバイザーは、ハイパーバイザー スケジューラの種類の設定に関係なく、従来のスケジューラの動作を使用します。

Hyper-V Hypervisor のさまざまな種類のスケジューラを理解して使用する | Microsoft Learn

今回利用した環境のプロセッサ AMD A10-5800K は 4 コアで構成され、かつ SMT は無効(サポートしていない)ようです。このために「コア スケジューラ」を選択しても「従来のスケジューラ、SMT は無効化」が選択されたようです。

今回の環境で試した設定と実際のスケジューラ動作を一覧にします。

設定 スケジューラ
Classic 従来のスケジューラ、SMT は無効化
Core 従来のスケジューラ、SMT は無効化
Root ルート スケジューラ

このように、クライアントシステムでもハイパーバイザースケジューラの設定をすることは可能です。ただし、「ルートスケジューラ」のみ公式にサポートされる構成であることに注意が必要です。