次の方法で共有


スレッド ビュー (並行処理のパフォーマンス)

スレッド ビューは、同時実行ビジュアライザーの中で最も詳細で多機能なビューです。 このビューを使用すると、同期処理や I/O などの理由でスレッドが実行されているか、ブロックされているかを特定できます。

プロファイル分析では、同期実行ビジュアライザーにより、すべてのオペレーティング システムのコンテキスト切り替えイベントが、アプリケーションのスレッドごとに調査されます。 コンテキスト切り替えは、次のようにさまざまな理由により発生します。

  • 同期プリミティブでスレッドがブロックされた

  • スレッドのクォンタムの期限が切れた

  • スレッドがブロックの原因となる I/O 要求を実行した

スレッド ビューは、スレッドが実行を停止したとき、すべてのコンテキスト切り替えにカテゴリを割り当てます。 カテゴリは、ビューの左下にある凡例に表示され、その説明は対応するヘルプ トピックに表示されます。 コンテキスト切り替えイベントのカテゴリ分けは、スレッドの呼び出し履歴から、ブロックの原因となっている既知の API を検索して行われます。 イベント内に対応する呼び出し履歴が見つからなかった場合、Windows により示される待機理由が使用されます。理論的には正しいのですが、Windows のカテゴリは、ユーザーの予想や目的ではなく実装の詳細に基づいている場合があります。たとえば、Windows は、ネイティブのスリム リーダー ライター ロックのブロックを同期ではなく I/O としてレポートします。ただし、このような場合は、コンテキスト切り替えイベントに対応する呼び出し履歴を調べることによって、ブロック イベントの根本的な原因を特定できます。

また、スレッド ビューには、スレッド間の依存関係も表示されます。 たとえば、同期オブジェクトでブロックされたスレッドを特定すると、通常はブロックを解除したスレッドも確認できます。また、そのスレッドが対象スレッドのブロックを解除したときの呼び出し履歴が表示されるので、そのときにそのスレッドが行っていた処理も確認できます。

さらに、スレッドの実行中にサンプルが収集されるため、実行セグメント中に 1 つ以上のスレッドで実行されるコードを、ユーザーが分析できるようになります。 このビューでは、スレッド実行をサンプル ベースで確認できるだけでなく、呼び出し履歴ツリーの実行プロファイリング レポートおよびブロック レポートも表示できます。

使用法

スレッド ビューの使用目的は多岐にわたります。 一般的な使用法は次のとおりです。

  • アプリケーションのユーザー インターフェイス (UI) が特定の実行フェーズ中に応答しない理由を特定する。

  • 同期、I/O、ページ フォールトなどによるブロック時間の総計を特定する。

  • システム上で実行されている他のプロセスによる干渉の程度を特定する。

  • 並列実行の負荷分散に関する問題を特定する。

  • 最大のスケーラビリティを実現できない理由や、スケーラビリティが不足している理由 (システムに多くの論理コアが備わっているにもかかわらず、並行アプリケーションのパフォーマンスが改善しない理由など) を特定する。

  • アプリケーション内の同時実行の程度を理解することにより、並列化の実現に役立てる。

  • 実行のワーカー スレッドとクリティカル パスの間の依存関係を把握する。

このセクションの後半では、このビューを効果的に操作するために推奨される使用法のパターンについて説明します。 まず、CPU 使用状況ビューを使用して、調査対象をプロセス実行の特定のフェーズに絞ることをお勧めします。 この作業では、アプリケーション内のシナリオ マーカーのサポート を活用することにより、作業効率を大幅に向上させることができます。 調査対象となる実行時間ウィンドウを絞り込んだら、スレッド ビューでの作業を開始します。

対象の領域を特定して絞り込む

スレッド ビューでは、タイムライン ビューの X 軸に時間が表示されます。 Y 軸には、プロファイル収集中に作業を行っていたシステム内の物理ディスク デバイスごとに、2 つの I/O チャネル (1 つは読み込み用、もう 1 つは書き込み用) が表示されます。 ディスク チャネルの下には、プロセス内の各スレッドのチャネルが表示されます。 初期状態では、スレッドは作成された順に並んでいるため、メインのアプリケーション スレッドが最初に表示されます。 ビューの左上隅にある並べ替えオプションを使用すると、他の条件 (最も多くの実行作業を行っているスレッドなど) でスレッドを並べ替えることができます。

次に、左側の列でスレッド名を選択し、ツール バーにある [選択したスレッドを非表示にします] アイコンをクリックすることにより、対象のシナリオ内の作業を実行していないスレッドを隠すことができます。 このようなスレッドが存在する原因は多数あります。 たとえば、アイドル スレッドのプール スレッドなどが挙げられます。 通常、このようなスレッドは完全にブロックされます (同期が原因であることが多い)。 その統計情報が記載されることで、レポートに関係のない情報が含まれないようにするために、これらのスレッドを削除する必要があります。

"実行ブレークダウン" タブ レポートを使用して、非表示にする追加スレッドを特定できます。 "実行ブレークダウン" グラフを表示するには、アクティブな凡例の [スレッド別の概要] をクリックします。 このグラフには、現在表示されている時間ウィンドウについて、アプリケーション内のスレッドに関するスレッド状態の内訳が表示されます。 グラフのスケーラビリティを保つために、表示されるスレッドの数は限られており、場合によっては、アプリケーション内のすべてのスレッドに関するデータが表示されないこともあります。 このような場合、右端に省略記号が表示されます。

これで、分析対象を特定の領域に絞り込み、調査対象スレッドを選択できたので、パフォーマンス分析を開始します。 以下のセクションでは、必要に応じて自由に使用できるさまざまなツールについて説明します。

スレッドのブロックの詳細

スレッドをブロックする領域の根本的な発生原因を把握するには、これらの領域のうちいずれかをポイントまたは選択 (クリック) します。 ブロックの原因となっている領域をポイントすると、ブロックの原因となるイベントについて、カテゴリ、ブロックの原因となっている API (存在する場合)、領域の開始時間、ブロックの期間などの一般情報を記載したツールヒントが表示されます。 カテゴリがプリエンプションであるイベントについては、スレッドがカーネルによって停止されたときに CPU でスケジュールされていたプロセスのプロセス ID とスレッド ID も表示されます。 また、対象チャネル内のブロックの原因となっている領域を選択して、下部のウィンドウに現在のスタックを表示することができます。 ツールヒントに表示される内容のほかに、[現在のスタック] タブに、スレッドのブロックの原因となった呼び出し履歴が表示されます。 呼び出し履歴を調べることで、スレッドをブロックしたイベントの根本的な原因を特定できます。 既定では、このビューにはすべての呼び出し履歴 (ユーザーおよびカーネルの履歴も含む) が表示されます。 ツールによって特定の API が原因であることがわかった場合は、呼び出し履歴はそのフレームを除いて縮小されます。 ツールによってブロックの原因となったルートの関数呼び出しを特定できない場合は、ユーザーが呼び出し履歴を調査して判断できるように、呼び出し履歴全体が公開されます。

実行パスによっては、ブロックの原因となるイベントが複数発生することもよくあります。 このため、ブロックによる累積遅延時間を、呼び出し履歴ごとに整理しておくと便利です。 これを実現するために、ブロックのカテゴリごとに、コール ツリーをベースとしたプロファイル レポートを表示する機能が用意されています。 左側にあるブロックのカテゴリの凡例で、いずれかの項目をクリックすると、プロファイルが表示されます。 これらのレポートにより、アプリケーションのパフォーマンス調整のために優先的に改善する必要がある場所を、すばやく判断できます。

スレッド間の依存関係

同時実行ビジュアライザーには、プロセス内でブロックの原因になっている、スレッド間の依存関係が表示されます。 どのスレッドのアクションが対象スレッドのブロックを解除したのかを判断するには、ブロックの原因になっている関連セグメントをクリックします。 ツールによりブロック解除スレッドが判断できた場合、ブロックの原因になっているセグメントに続く実行セグメントと、もう一方のスレッドとが線で結ばれます。 この線により、選択されたスレッドのブロックを別のスレッドがどのように解除したのかが示されます。 さらに、[ブロック解除スタック] タブに関連する呼び出し履歴が表示されます。 このように、ブロックされているスレッドをすばやく特定し、スレッドで行われようとしていたこと、また、最終的にどのようにして実行が許可されたのかを確認することができます。

スレッド実行の詳細

アプリケーションが実行されているときに、スレッドによって実行されるコードを特定できると便利な場合がよくあります。 これらの領域は、タイムライン グラフで緑のセグメントとして表示されます。 この作業に役立つ機能が 2 つあります。

まず、タイムラインで実行セグメントをクリックすると、最も近いサンプル プロファイルの呼び出し履歴が検索されます。 検索が成功すると、実行ブロック内のサンプル採取位置の上に黒のキャレット (^) が表示され、[現在のスタック] タブに呼び出し履歴が表示されます。 実行セグメントの他の場所をクリックすると、他のサンプルを選択できます。 サンプルを検索できない場合もあります。 これは、通常、サンプル プロファイルの収集に 1 ミリ秒の時間制限があることが原因です。 たとえば、実行セグメントが 1 ミリ秒未満である場合には、呼び出し履歴が収集されない可能性があります。 サンプリング頻度は変更できませんが、正確性と実行に伴うオーバーヘッドのバランスを考慮すると、1 ミリ秒が最良であると考えられます。

次に、実行に時間がかかっている場所を特定するために役立つ重要な機能として、実行のサンプリング プロファイル レポートとそのコール ツリー ビューが挙げられます。 この機能を使用するには、アクティブな凡例の [実行] という項目をクリックします。 実行プロファイルでは、ウィンドウ内の時間範囲によって抽出された、現在のビューのすべての有効な (非表示でない) スレッドについて、サンプル レポートが表示されます。

タイムライン グラフ

タイムライン グラフには、プロセス内のすべてのスレッド、およびホスト コンピューター上のすべての物理ディスク デバイスのアクティビティが表示されます。 タイムラインを拡大するには、マウス ポインターをドラッグするか、ウィンドウのツール バーのズーム スライダーを使用するか、Ctrl キーを押しながらマウスのホイールを回転させます。 いずれかの水平バーまたはセグメントをポイントすると、スレッドのそのポイントのカテゴリ、開始時間、および存続期間が表示されます。 いずれかのセグメントをクリックすると、[現在のスタック] タブの下部に呼び出し履歴が表示されます。

タイムライン グラフでは、特定の時点におけるスレッドの状態が色で示されます。 たとえば、緑色のセグメントは実行中、赤色のセグメントは同期のためにブロックされた状態、黄色のセグメントはプリエンプションによってブロックされた状態、紫色のセグメントはデバイスの I/O に割り当てられた状態を示します。 このビューは、並行ループまたは同時実行タスクに含まれるスレッド グループの作業バランスを調べるのに役立ちます。 1 つまたは複数のスレッドが、他のスレッドよりも完了までに時間がかかっている場合、作業負荷のバランスが崩れている可能性があるため、スレッド間でより公平に作業を割り振ることにより、プログラムのパフォーマンスが向上する可能性があります。

また、タイムライン グラフを使用して、スレッド間の依存関係を調べることや、ブロックの原因となっているスレッドと、ブロックされているスレッドの時間的な関係を調べることもできます。 特定の時間に実行されているスレッドの数を調べるには、タイムラインのそのポイントの縦方向のスライスを確認します。 そのポイントで緑色の (実行中の) スレッドが 1 つしかない場合、アプリケーションでシステムの同時実行能力がすべて活かされていないことを示しています。 ツール バーの [上へ] および [下へ] をクリックして、個々のスレッドの並べ替えや移動ができるほか、[スレッドを隠す] をクリックすると、重要でないスレッドを隠すことができます。

プロファイル レポート

タイムライン グラフの下には、アクティブな凡例とタブ付きウィンドウがあり、複数のレポートが表示されます。 プロファイル レポートは、スレッドの拡大、スクロール、非表示、または非表示解除によりスレッド ビューが変更されると、自動的に更新されます。 大規模なトレースの場合、更新レポートの計算中は、レポート ウィンドウが淡色表示になります。 各レポートには、[不要項目の非表示] と [マイ コードのみ] という 2 つのフィルターがあります。 [不要項目の非表示] では、ほとんど時間が費やされず、重要でないコール ツリー エントリが除外されます。 既定値は 2% です。ただし、0% ~ 99% まで調整できます。 [マイ コードのみ] チェック ボックスでは、自分以外のコール ツリー エントリを除外または表示することができます。 以降では、使用できるレポートについて説明します。

プロファイル レポート

このタブには、現在のプロファイル レポートが表示されます。 アクティブな凡例のエントリをクリックすると、表示するプロファイル レポートを指定できます。 以下の「実行」以降のプロファイル レポートを使用できます。

現在のスタック

このタブには、詳細グラフで選択したスレッド セグメントの呼び出し履歴が表示されます。 呼び出し履歴は、プログラムに直接関連するアクティビティだけを表示するよう縮小されています。 選択項目ウィンドウには、現在実行されているスレッドの情報が、直ちに表示されます。

ブロック解除スタック

[ブロック解除スタック] をクリックすると、このスレッドのブロックを解除したスレッド、およびコード行が表示されます。

実行

実行プロファイル レポートには、各スレッドがさまざまな状態 (実行、I/O、メモリ管理など) にあった時間のパーセンテージを示す詳細な表が表示されます。

コール ツリー エントリの横にあるツリー コントロールをクリックすると、その実行時間に該当するコード行を調べることができます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 呼び出しサイトが 1 つだけの場合は、[呼び出しサイトの表示] をクリックすると、呼び出しサイトの強調表示されたコード行へ移動します。 呼び出しサイトが複数ある場合は、ダイアログ ボックスが表示され、エントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに移動すると便利です。 詳細については、「実行プロファイル レポート」を参照してください。

同期

同期レポートには、同期ブロックの原因となった呼び出しが表示されると共に、各呼び出し履歴のブロック時間の総計が表示されます。 この情報を使用して、対象となる領域を特定し、調査することができます。

コール ツリー エントリの横にあるツリー コントロールをクリックすると、その同期の時間に該当するコード行を調べることができます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 呼び出しサイトが 1 つだけの場合は、クリックすることにより、呼び出しサイトの強調表示されたコード行に接続されます。 呼び出しサイトが複数ある場合は、ダイアログ ボックスが表示され、エントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに接続すると便利です。 詳細については、「同期時間」を参照してください。

入出力

I/O レポートには、I/O ブロックの原因となった呼び出しが表示されると共に、各呼び出し履歴のブロック時間の総計が表示されます。 この情報を使用して、対象となる領域を特定し、調査することができます。

呼び出し履歴の横のあるツリー コントロールをクリックすると、その I/O の時間に該当するコード行が調べられます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 呼び出しサイトが 1 つだけの場合は、クリックすることにより、呼び出しサイトの強調表示されたコード行に接続されます。 呼び出しサイトが複数ある場合は、ダイアログ ボックスが表示され、エントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに接続すると便利です。 詳細については、「I/O 時間 (スレッド ビュー)」を参照してください。

スリープ

スリープ レポートには、スリープ ブロックの原因となった呼び出しが表示されると共に、各呼び出し履歴のブロック時間の総計が表示されます。 この情報を使用して、対象となる領域を特定し、調査することができます。

呼び出し履歴の横のあるツリー コントロールをクリックすると、そのスリープの時間に該当するコード行が調べられます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 使用できる呼び出しサイトが 1 つだけの場合は、クリックすることにより、呼び出しサイトの強調表示されたコード行に接続されます。 複数の呼び出しサイトを使用できる場合は、ダイアログ ボックスが表示され、そこからエントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに接続すると便利です。 詳細については、「スリープ時間」を参照してください。

ページング

ページング レポートには、プリエンプション ブロックの原因となった呼び出しが表示されると共に、各呼び出し履歴のブロック時間の総計が表示されます。 この情報を使用して、対象となる領域を特定し、調査することができます。 通常、プリエンプションは、コードが原因ではなくオペレーティング システムによってプロセスに設定されるため、このブロック レポートは他のレポートに比べて利用可能性が低くなります。 発生したプリエンプションの種類、発生場所、およびプロセスが指定したプリエンプション状態であった時間が表示されます。

コール ツリー エントリの横にあるツリー コントロールをクリックすると、そのプリエンプションの時間に該当するコード行を調べることができます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 使用できる呼び出しサイトが 1 つだけの場合は、[呼び出しサイトの表示] をクリックすると、呼び出しサイトの強調表示されたコード行へ直接移動します。 複数の呼び出しサイトを使用できる場合は、ダイアログ ボックスが表示され、そこからエントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに接続すると便利です。 詳細については、「メモリ管理時間」を参照してください。

優先

ページング レポートには、プリエンプション ブロックの原因となった呼び出しが表示されると共に、各呼び出し履歴のブロック時間の総計が表示されます。 この情報を使用して、対象となる領域を特定し、調査することができます。 通常、プリエンプションは、コードが原因ではなくオペレーティング システムによってプロセスに設定されるため、このブロック レポートは他のレポートに比べて利用可能性が低くなります。 発生したプリエンプションの種類、発生場所、およびプロセスが指定したプリエンプション状態であった時間が表示されます。

呼び出し履歴の横にあるツリー コントロールをクリックすると、そのプリエンプションの時間に該当するコード行を調べることができます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 使用できる呼び出しサイトが 1 つだけの場合は、[呼び出しサイトの表示] をクリックすると、呼び出しサイトの強調表示されたコード行へ直接移動します。 複数の呼び出しサイトを使用できる場合は、ダイアログ ボックスが表示され、そこからエントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに接続すると便利です。 詳細については、「優先時間」を参照してください。

UI 処理

UI 処理レポートには、UI 処理ブロックの原因となった呼び出しが表示されると共に、各呼び出し履歴のブロック時間の総計が表示されます。 この情報を使用して、対象となる領域を特定し、調査することができます。

コール ツリー エントリの横にあるツリー コントロールをクリックすると、その UI 処理の時間に該当するコード行を調べることができます。 調査対象のコール ツリー エントリを特定したら、エントリを右クリックして、[ソースを表示] および [呼び出しサイトの表示] というコンテキスト メニューを表示します。 [ソースの表示] をクリックすると、ソース コードへ移動し、[呼び出しサイトの表示] をクリックすると、この呼び出しを行ったコード行へ移動します。 使用できる呼び出しサイトが 1 つだけの場合は、クリックすることにより、呼び出しサイトの強調表示されたコード行に接続されます。 複数の呼び出しサイトを使用できる場合は、ダイアログ ボックスが表示され、そこからエントリを 1 つ選択できます。 [ソースに移動] をクリックすると、強調表示された呼び出しサイトへ移動します。 通常は、インスタンス数が最も多い呼び出しサイト、最も時間を費やしている呼び出しサイト、またはそれら両方の状態にある呼び出しサイトを選択し、そのソースに接続すると便利です。 詳細については、「UI 処理時間」を参照してください。

スレッド別の概要

このタブには、各スレッドが各状態 (実行、ブロック、I/O 操作など) にあった時間の総計を色別に表した棒グラフが表示されます。 棒の最下部にはラベルが表示されます。 既定のズーム レベルでは、メイン スレッドが一番左の棒になります。 詳細グラフでズーム レベルを調整すると、タブ レポートは自動的に更新され、新しいタイム スケールが反映されます。 このグラフのスケーラビリティを保つために、表示されるスレッドの数は限られており、 場合によっては、アプリケーション内のすべてのスレッドに関するデータが表示されないこともありますが、その場合、右端に省略記号が表示されています。 グラフに表示されていないスレッドを確認する必要がある場合は、その目的のスレッドがグラフ内に表示されるまで、必要のないスレッドを非表示にします。 詳細については、「スレッド別の概要レポート」を参照してください。

ファイル操作

このタブには、ディスク I/O に割り当てられていたスレッドと、そのスレッドによって影響を受けたファイルが表示されます。 これには、読み込まれた DLL、読み取られたバイト数などの情報が含まれます。 このレポートは、特にプロセスが I/O 主体であるような場合、実行中にファイルにアクセスするのにかかる時間を評価するのに役立ちます。 詳細については、「ファイル操作レポート (スレッド ビュー)」を参照してください。

参照

概念

同時実行ビジュアライザー