高いコンテキスト切り替えレート
このトピックでは、コンテキスト切り替えが頻繁に発生し、タイトルのパフォーマンスが低下しているスレッドを見つける方法について説明します。 コンテキスト切り替えは、後の時点で実行を再開するために復元できるよう、スレッドの状態を保存するプロセスです。 スレッド間で素早くコンテキストを切り替える動作は、CPU 使用率の観点から高負荷です。 各コンテキスト スイッチでは、カーネルは処理に約 5 μs (平均) かかります。 ただし、、結果として発生する、数値化が困難なキャッシュ ミスによって実行時間が追加されます。 コンテキスト切り替えの頻度が高くなると、CPU 使用率が低下します。 各タイトルは異なりますが、妥当な目標は、コアあたり 1 秒あたりのコンテキスト切り替えを 1,000 回未満にすることです。
PIX
PIX は、タイトルが実行している 1 秒あたりのコンテキスト切り替え数を提供しませんが、コンテキスト切り替え率が高すぎる場合に関する非常に役立つ考察を提供します。
コンテキスト切り替え率が高すぎるかどうかを判断するには
タイミング キャプチャーを生成します。 詳細については、「一般的な手順」をご覧ください。
[タイムライン] ビューで CPU コアを確認します (図 1 を参照)。 赤の目盛りがコンテキスト切り替えを表しています。 この場合、コア 1 から 5 は、キャプチャの全秒数として赤い実線を示しています。 これは極端な例ですが、赤色の密度が高い領域は、タイトルのコンテキスト切り替えが多すぎることを良く示しています。
図 1: コンテキスト切り替えが非常に多い CPU コアを示している PIX タイミング キャプチャ。
拡大して 1 つのフレームを検査します (図 2 を参照)。 この例ではちょうど 30 ms です。 ほとんどのタイムラインは完全に赤で表示され、多くの迅速なコンテキスト切り替えを示しています。 このように密な赤いタイムラインは、コンテキスト切り替え率が高すぎる強力なインジケーターです。
図 2: コンテキスト切り替え回数が多いことを示すタイミング キャプチャの 30 ms セクションの拡大。
[Items to Show] (表示するアイテム) で、[Context Switches] (コンテキスト切り替え) を選び、[Range Details] (範囲の詳細) タブを表示します (図 3 を参照)。 ここでは、選択した時間範囲で発生したコンテキスト切り替え一覧を表示できます。 このビューは、タイミング キャプチャで特定のコンテキスト切り替えを選択し、調査するのに役立ちます。
図 3: タイミング キャプチャのコンテキスト切り替えの一覧を示す PIX の [Range Details] (範囲の詳細) タブ。
コンテキスト切り替えを選択し、[Element Details] (要素の詳細) パネルを調べて、これらのスレッドでコンテキスト切り替えが発生した理由を判断できます。
Windows Performance Analyzer (WPA)
WPA でコンテキスト切り替え率を評価するために最適なウィンドウは、[CPU Usage (Precise) Context Switch Count by Process, Thread] です (図 4 を参照)。 これは ThreadContextSwitch.wpaProfile
WPA プロファイルの一部です。 図 4 のグラフは、グラフに表示されている部分に基づいてコンテキスト切り替え率を示しています。 拡大すると、グラフ上のポイントの生成に使われる時間範囲が変わるため、表示量は重要です。 このグラフの最適な使用法は、コンテキスト切り替えが急上昇している時間を識別するために使用することです。 この表では、ある期間中の状況に注目して、発生したコンテキスト切り替え数を確認できます。
WPA を使ってコンテキスト切り替えが多いスレッドを見つけるには
イベント トレース ログ (ETL) ファイルを生成します。 詳細については、「一般的な手順」をご覧ください。
「一般的な手順」の説明に従って、
ThreadContextSwitch.wpaProfile
WPA プロファイルを適用します。 図 4 は [New analysis] (新しい分析) タブの外観を示しています。図 4: コンテキスト切り替え数が多いことを示している [WPA CPU Usage (Precise) Context Switch Count by Process Thread] ビュー。
注意
図 4 のシステムも、コンテキスト切り替え回数が非常に多く、CPU リソースの 1.34 パーセントを使用していることがわかります。 これは、ETL データを収集するオーバーヘッドのためです。 ETL イベントは軽量ですが、トレースは引き続きすべてのコンテキスト切り替えでコール スタック データを収集します。 この場合、30 秒で 800 万回を超えています。これは小さな影響を与える可能性があります。
コンテキスト切り替えが多いかもしれないように見える 1 秒の領域を拡大します。
図 5 のデータ表の [Count] (カウント) 列を確認して、コンテキスト切り替えが最も多いスレッドを確認できます。 似た数のスレッドがあることがあります。これは、対象のスレッドが相互に切り替わっていることを示します。
図 5: コンテキスト切り替え率が高い場合の表示を示す時間間隔。 ビューに合わせて縮尺が調整されます。
回数が最も多いコール スタックを展開して、コードで関連する場所を見つけます。
表の右クリック メニューで [Find In Column] (列で検索) を選択して、同じプリミティブまたは関数を使用している可能性がある他のスレッドを見つけます (図 6 を参照)。
図 6: 検索機能を使用して AcquireLock 関数のすべての呼び出しを見つけます。この関数は、コンテキスト切り替えが頻繁に発生する原因であるとわかっています。
コンテキスト切り替え回数を高める一般的な原因
次の表に、コンテキスト切り替え率が高くなる一般的な原因を示します。
原因 | Reason |
---|---|
スレッド プリミティブの競合。 たとえば、重要セクションです。 | 同じ CRITICAL_SECTION を使用しているタイトル スレッドが多すぎる。 |
他のスレッドが「実行できる状態」でのタイト ループの SwitchToThread。 | 別のスレッドが実行する準備が整っている場合であれば、常にコンテキスト切り替えになります。 |
優先順位の高いスレッドのすばやい実行可能状態への切り替え。 | 優先度の高いスレッドのブロックを解除すると、OS はコンテキスト切り替えを自動的に実行します。 |