パフォーマンス プロファイラーで CPU のプロファイルを使用してパフォーマンスを分析する (C#、Visual Basic、C++、F#)
アプリのパフォーマンスの問題の調査を開始するのに適した方法は、CPU プロファイラーを使用してアプリの CPU 使用率を把握することです。 CPU 使用率 パフォーマンス ツールは、C++、C#/Visual Basic でコードを実行するのに費やされた CPU アクティブ計算時間と割合を表示します。
CPU 使用率ツールは、次の場合に役立ちます。
チームのコードベースで速度の低下またはプロセスのハングを診断します。 このツールは、チームの運用コードに関する問題を診断するのに役立ちます。 このツールには、自動的な分析情報とデータのさまざまなビューが用意されており、パフォーマンスの問題を分析および診断できます。
DevOps のシナリオでパフォーマンスの問題を特定します。たとえば、繁忙期に小売店の Web サイトで一部の要求や注文が通らないという報告を顧客から受けた場合などです。 多くの場合、問題は運用環境にあり、その時点でデバッグするのは困難ですが、このツールを使うと、問題の十分な情報と証拠をキャプチャすることができます。 トレース ファイルを収集した後、分析によって潜在的な原因をすばやく理解し、コードのコンテキスト内で提案を受けることができるので、問題を修正するための次の手順を実行できます。
待機時間の問題が API 要求内にない場合は、CPU 使用率の高さやその他の関連する問題を CPU 使用率ツールで確認できます。 CPU 使用率ツールはボトルネックを特定するのに役立ち、最適化する場所を絞り込むことができます。
CPU 使用率ツールは、ローカル トレース セッションと運用環境の両方に役立ちます。 CPU 使用率ツールは、キーボード ショートカット Alt + F2 キーを押してから [CPU 使用率] を選ぶか、dotnet-trace や dotnet-monitor などのツールを使って既に収集されたトレースを開くことにより、開始することもできます。 (.NET の運用コードの場合、トレースを収集するにはおそらくこの方法が最もよく使われます)。
CPU 使用率ツールは、開かれた状態の Visual Studio プロジェクトまたはインストール済みの Microsoft Store アプリで実行することができます。または、実行中のアプリまたはプロセスにアタッチすることもできます。 CPU 使用率ツールは、デバッグを使用して、または使用せずに実行することができます。 詳細については、「デバッガーを使用して、または使用せずにプロファイリング ツールを実行する」を参照してください。
次の手順では、Visual Studio パフォーマンス プロファイラーを使用してデバッガーなしで CPU 使用率ツールを使用する方法を示します。 例では、ローカル コンピューターでリリース ビルドを使用しています。 リリース ビルドでは、実際のアプリ パフォーマンスの最適なビューが提供されます。 CPU 使用率ツールを使用してパフォーマンスを向上させる方法を説明するチュートリアルについては、「コードの最適化に関する初級者向けガイド」を参照してください。
通常、ローカル コンピューターでは、インストールされているアプリの実行が最適にレプリケートされます。 リモート デバイスからデータを収集するには、リモート デスクトップ接続を介さずに、デバイス上で直接アプリを実行します。
CPU 使用率データを収集する
Visual Studio プロジェクトで、ソリューション構成を [リリース] に設定し、配置ターゲットとして [ローカル Windows デバッガー] (または [ローカル コンピューター] ) を選択します。
[デバッグ]>[パフォーマンス プロファイラー] の順に選択します。
[使用可能なツール] の下で、 [CPU 使用率] を選択し、 [開始] を選択します。
プロファイラーを起動する前に [コレクションを一時停止した状態で開始] オプションを有効にした場合、診断セッション ビューで [記録] ボタンを選択するまでデータは収集されません。
Note
ツールの効率を向上させる方法の詳細については、「プロファイラー設定の最適化」を参照してください。
アプリが起動すると、診断セッションが開始され、CPU 稼働率データが表示されます。 データの収集が完了したら、 [コレクションの停止] を選択します。
CPU 使用率ツールがデータを分析してレポートを表示します。 データの収集または表示に問題がある場合は、「プロファイル エラーのトラブルシューティングと問題の修正」をご覧ください。
表示するスレッドを選択または選択解除するには、 [フィルター] ドロップダウンを使用します。特定のスレッドまたはノードを検索するには、 [検索] ボックスを使用します。
CPU 稼働率データ列
名前 | 説明 |
---|---|
合計 CPU [ユニット、%] | ![]() 選択した時間範囲内で、関数の呼び出しと関数によって呼び出された関数によって使用された CPU 計算時間のミリ秒と CPU 使用率。 これは、特定の時間範囲におけるアプリの合計 CPU アクティビティと、利用可能な合計 CPU とを比較する CPU 使用率タイムライン グラフとは異なります。 |
セルフ CPU [ユニット、%] | ![]() 関数によって呼び出された関数を除き、選択した時間範囲内で関数の呼び出しによって使用された CPU 計算時間のミリ秒数と CPU 使用率。 |
Module | 一部のビューでは、[モジュール] 列が表示され、関数を含むモジュールの名前が示されます。 |
CPU 分析情報を分析する
トップ インサイト セクションにインサイトが表示された場合は、提供されているリンクを使用して、特定された問題に関する詳細情報を取得します。 さらに、Copilot を使用している場合は、 「Copilot に質問」 ボタンをクリックすると Copilot チャット ウィンドウが開き、コードと特定された問題に基づいて Copilot から提案が提供されます。
上位の分析情報、上位の関数、ホット パスを分析する場合は、CPU 分析情報に関するページを参照してください。
CPU 稼働率を分析する
CPU 使用率レポートを分析するには、[詳細を開く] をクリックするか、上位の関数のいずれかをクリックして [関数] ビューを開きます。
レポートには、診断データのさまざまなビューが示されます。
- 呼び出し元/呼び出し先
- コール ツリー
- モジュール
- 関数
- フレーム グラフ
レポートを分析するには、[詳細レポートの作成] をクリックします。
レポートには、診断データのさまざまなビューが示されます。
- 呼び出し元/呼び出し先
- コール ツリー
[呼び出し元/呼び出し先] を除くすべてのビューで、診断レポートは、合計 CPU の高い順に並べ替えられます。 並べ替え順序または並べ替え列を変更するには、列ヘッダーを選択します。 目的の関数をダブルクリックすると、関数のソースと、その関数に費やされた時間を示す強調表示が表示されます。 この表には、関数で費やされた時間 (呼び出された関数 (合計 CPU) を含む) や、関数で費やされた時間を示す 2 番目の列 (呼び出された関数 (セルフ CPU) を除く) などのデータを含む列が示されています。
このデータは、関数自体がパフォーマンスのボトルネックであるかどうかを評価するのに役立ちます。 サード パーティのコードまたはランタイム ライブラリがエンドポイントの速度低下やリソース消費量の多い理由であるかどうかを確認するために、メソッドが表示するデータの量を決定します。
フレーム グラフの使用について詳しくは、「フレーム グラフを使用してホット パスを識別する」を参照してください。
CPU 使用率の呼び出しツリー
コール ツリーを表示するには、レポートの親ノードを選択します。 既定では、[CPU 使用率] ページが開き、[呼び出し元/呼び出し先] ビューが示されます。 [現在のビュー] ドロップダウンで [コール ツリー] を選択します。
[ホット パスの展開] と [ホット パスの表示] ボタンをクリックすることで、最も高い割合で CPU を使用している関数の呼び出しを呼び出しツリー ビューに表示できます。
コール ツリーの構造
画像 | 説明 |
---|---|
![]() |
アプリケーションを表す、CPU 使用率呼び出しツリーの最上位ノード。 |
![]() |
ほとんどのアプリでは、 [外部コードの表示] オプションが無効になっていると、2 番目のレベルのノードが、 [外部コード] ノードになります。 ノードには、アプリの開始と停止、UI の描画、スレッドの制御、およびアプリへの他の低レベル サービスの提供を行うシステムとフレームワーク コードが含まれています。 |
![]() |
セカンド レベル ノードの子はユーザー コード メソッドおよび非同期ルーチンで、セカンド レベル システムとフレームワーク コードによって呼び出される、または作成されます。 |
![]() |
メソッドの子ノードには、親メソッドを呼び出すためだけのデータが含まれます。 [ 外部コードの表示 ] がオフのとき、アプリ メソッドには [外部コード] ノードが含まれる場合もあります。 |
外部コード
コードによって実行されるシステムおよびフレームワークの関数は、外部コードと呼ばれます。 外部コード関数は、アプリの開始と停止、UI の描画、スレッドの制御、およびアプリへの他の低レベル サービスの提供を行います。 外部コードを確認することはほとんどないため、CPU 使用率コール ツリーはユーザー メソッドの外部関数を 1 つの [外部呼び出し] ノードにまとめます。
外部コードの呼び出しパスを表示するには、メイン レポートの概要ページ (右側のペイン) で、 [設定] ドロップダウンから [マイ コードのみを表示] を選択し、 [適用]を選択します。 [CPU 使用率] ページの [コール ツリー] ビューで外部コードの呼び出しが展開されます。 (設定 ドロップダウンは、詳細ビューではなく、メインのレポート概要ページで使用できます。)
コードによって実行されるシステムおよびフレームワークの関数は、外部コードと呼ばれます。 外部コード関数は、アプリの開始と停止、UI の描画、スレッドの制御、およびアプリへの他の低レベル サービスの提供を行います。 外部コードを確認することはほとんどないため、CPU 使用率コール ツリーはユーザー メソッドの外部関数を 1 つの [外部コード] ノードにまとめます。
外部コードの呼び出しパスを表示するには、診断レポートのメイン ページ (右側のウィンドウ) で、 [フィルター] ドロップダウンから [外部コードの表示] を選択し、 [適用] を選択します。 [CPU 使用率] ページの [コール ツリー] ビューで外部コードの呼び出しが展開されます。 ( [フィルター] ドロップダウンは、詳細ビューではなくメインの診断ページで使用できます。)
多くの外部コードの呼び出しチェーンは複雑な入れ子になっているため、チェーンの幅が [関数名] 列の表示幅に収まりきらない可能性があります。 次の図に示すように、関数名が表示されます。
多くの外部コードの呼び出しチェーンは複雑な入れ子になっているため、チェーンの幅が [関数名] 列の表示幅に収まりきらない可能性があります。 その場合、関数名が ... として表示されます。
探している関数名を検索するには、検索ボックスを使用します。 選択した行をポイントするか、水平スクロール バーを使用してデータを表示します。
CPU 使用率コール ツリー内の非同期関数
コンパイラが非同期メソッドを検出すると、メソッドの実行を制御するために非表示のクラスを作成します。 概念的に、クラスはステート マシンです。 クラスには、元のメソッドを非同期に呼び出すコンパイラにより生成された関数と、それらを実行するために必要なコールバック、スケジューラ、反復子があります。 親メソッドによって元のメソッドが呼び出されると、コンパイラは親の実行コンテキストからメソッドを削除し、アプリの実行を制御するシステムとフレームワーク コードのコンテキストにある非表示のクラスのメソッドを実行します。 非同期のメソッドは、多くの場合、1 つ以上の異なるスレッドで実行されます (必ずそうなるわけではありません)。 このコードは、CPU 使用率コール ツリーで、ツリーのトップ ノードのすぐ下にある [外部コード] ノードの子として表示されます。
次の例では、[外部コード] の下にある最初の 2 つのノードは、ステート マシン クラスのコンパイラ生成メソッドです。 3 番目のノードは、元のメソッドへの呼び出しです。
生成されたメソッドを展開して、詳細を表示します。
MainPage::GetMaxNumberAsyncButton_Click
は単に、タスクの値のリストを管理し、結果の最大値を計算し、出力を表示します。MainPage+<GetMaxNumberAsyncButton_Click>d__3::MoveNext
は、GetNumberAsync
の呼び出しをラップする 48 個のタスクをスケジュールして起動するために必要なアクティビティを表示します。MainPage::<GetNumberAsync>b__b
はGetNumber
を呼び出すタスクのアクティビティを表示します。
呼び出し回数を収集する (.NET)
関数ビューで呼び出し回数を表示する場合は、プロファイラーを起動する前に設定を有効にできます。 この設定は .NET プロジェクトの種類でサポートされており、プロファイラーでプロセスを起動する必要があります。 アタッチ シナリオはサポートされていません。
パフォーマンス プロファイラーで CPU 使用率の [設定] アイコンを選びます。
[Collect call counts (.NET only)] (呼び出し回数の収集 (.NET のみ)) オプションを有効にします。
CPU 使用率のデータを収集します。
関数ビューを開き、[呼び出し回数] 列が表示されるように設定されていることを確認します。
列が表示されない場合は、列の見出しを右クリックして表示する列を選びます。