パフォーマンス プロファイラーで CPU プロファイリングを使用してパフォーマンスを分析する (C#、Visual Basic、C++、F#)
アプリのパフォーマンスの問題の調査を開始するのに適した方法は、CPU プロファイラーを使用して CPU 使用率を理解することです。 Visual Studio の CPU 使用率パフォーマンス ツールは、C++、C#/Visual Basic でコードを実行するのにかかった CPU アクティブ計算時間と割合を示します。
CPU 使用率ツールは、次の場合に役立ちます。
チームのコードベースで速度の低下またはプロセスのハングを診断します。 このツールは、チームの運用コードに関する問題を診断するのに役立ちます。 このツールには、自動的な分析情報とデータのさまざまなビューが用意されており、パフォーマンスの問題を分析および診断できます。
DevOps のシナリオでパフォーマンスの問題を特定します。たとえば、このツールは、繁忙期に小売店の Web サイトで一部の要求や注文が通らないという報告を顧客から受けた場合などに役立ちます。 多くの場合、問題は運用環境にあり、その時点でデバッグするのは困難ですが、このツールを使うと、問題の十分な情報と証拠をキャプチャすることができます。 トレース ファイルを収集した後、分析によって潜在的な原因をすばやく理解し、コードのコンテキスト内で提案を受けることができるので、問題を修正するための次の手順を実行できます。
高い CPU 使用率を確認する。待機時間の問題が 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 使用率] を選んでから [開始] を選びます。
を選択する
を選択する
プロファイラーを起動する前に [コレクションを一時停止した状態で開始] オプションを有効にした場合、診断セッション ビューで [記録] ボタンを選択するまでデータは収集されません。
注
ツールの効率を向上させる方法の詳細については、「プロファイラー設定の最適化」を参照してください。
アプリが起動すると、診断セッションが開始され、CPU 使用率データが表示されます。 データの収集が完了したら、[収集の停止] を選択します。
CPU 使用率ツールがデータを分析してレポートを表示します。 データの収集または表示に問題がある場合は、「プロファイル エラーのトラブルシューティングと問題の修正」をご覧ください。
表示するスレッドを選択または選択解除するには、[フィルター] ドロップダウンを使用します。特定のスレッドまたはノードを検索するには、[検索] ボックスを使用します。
CPU 使用率データ列
名前 | 説明 |
---|---|
合計 CPU [ユニット、%] | ![]() 選択した時間範囲において、関数の呼び出し、および関数が呼び出した関数で使用された CPU 計算時間 (ミリ秒) と CPU の割合です。 これは、特定の時間範囲におけるアプリの合計 CPU アクティビティと、利用可能な合計 CPU とを比較する CPU 使用率タイムライン グラフとは異なります。 |
セルフ CPU [ユニット、%] | ![]() 関数が呼び出した関数を除いて、選択した時間範囲において、関数の呼び出しで使用された CPU 計算時間 (ミリ秒) と CPU の割合です。 |
モジュール | 一部のビューでは、[モジュール] 列が表示され、関数を含むモジュールの名前が示されます。 |
CPU の分析情報を分析する
[上位の分析情報] セクションに分析情報が表示される場合は、指定されたリンクを使用して、特定された問題に関する詳細情報を取得します。 さらに、Copilot を使用している場合は、[Copilot に質問する] ボタンを押すと、Copilot チャット ウィンドウが開き、コードと特定された問題に基づいて提案が Copilot から提供されます。
詳細については、CPU 分析情報に関する記事を参照してください。
CPU 使用率を分析する
CPU 使用率レポートを分析するには、[詳細を開く] をクリックするか、上位の関数のいずれかをクリックして [関数] ビューを開きます。
レポートには、診断データのさまざまなビューが示されます。
表示 | 説明 |
---|---|
呼び出し元/呼び出し先 | 特定の関数の CPU 時間、それを呼び出した関数、および呼び出す関数の詳細ビュー。 パフォーマンス データは、データ収集期間に対して集計されます。 呼び出し元の関数と呼び出された関数を選択して、呼び出しパスを走査できます。 |
呼び出しツリー | 関数呼び出しパスの階層ビュー。 CPU 時間が最も長い呼び出しパス (ホット パス) を識別するために使用されます。 |
モジュール | 個々のモジュールで費やされた CPU 時間を、データ収集期間にわたって集計したビュー。 高い呼び出し数やパフォーマンスの問題の組み合わせによってパフォーマンスのボトルネックになる可能性があるモジュールを特定するために使用されます。 |
関数 | 個々の関数で費やされた CPU 時間を、データ収集期間にわたって集計したビュー。 高い呼び出し数やパフォーマンスの問題の組み合わせによってパフォーマンスのボトルネックになる可能性がある関数を特定するために使用されます。 |
フレーム グラフ | フレーム グラフの視覚化における関数呼び出しパスの階層ビュー。 CPU 時間が最も長い呼び出しパス (ホット パス) を識別するために使用されます。 |
レポートを分析するには、[詳細レポートの作成] をクリックします。
レポートには、診断データのさまざまなビューが示されます。
- 呼び出し元/呼び出し先
- 呼び出しツリー
[呼び出し元/呼び出し先] を除くすべてのビューで、診断レポートは、合計 CPU の高い順に並べ替えられます。 並べ替え順序または並べ替え列を変更するには、列ヘッダーを選択します。 目的の関数をダブルクリックすると、関数のソースと、その関数に費やされた時間を示す強調表示が表示されます。 この表には、関数に費やされた時間を示す列があり、呼び出された関数を含む時間 (合計 CPU) と、呼び出された関数を除いた時間 (セルフ CPU) を示す2つの列が含まれています。
このデータは、関数自体がパフォーマンスのボトルネックであるかどうかを評価するのに役立ちます。 サード パーティのコードまたはランタイム ライブラリがエンドポイントの速度低下やリソース消費量の多い理由であるかどうかを確認するために、メソッドが表示するデータの量を決定します。
フレーム グラフの使用について詳しくは、「フレーム グラフを使用してホット パスを識別する」を参照してください。
CPU 使用率の呼び出しツリー
呼び出しツリーを表示するには、レポートの親ノードを選択します。 既定では、[CPU 使用率] ページが開き、[呼び出し元/呼び出し先] ビューが示されます。 [現在のビュー] ドロップダウンで [呼び出しツリー] を選びます。
[ホット パスの展開] と [ホット パスの表示] ボタンをクリックすることで、最も高い割合で CPU を使用している関数の呼び出しを呼び出しツリー ビューに表示できます。
呼び出しツリーの構造
画像 | 説明 |
---|---|
手順 1ProcGuid_1手順 1ProcGuid_1をする | アプリケーションを表す CPU 使用率呼び出しツリーの最上位ノード。 |
手順 2ProcGuid_2手順 2ProcGuid_2をする | ほとんどのアプリでは、[外部コードの表示] オプションが無効になっていると、2 番目のレベルのノードが、[外部コード] ノードになります。 ノードには、アプリの開始と停止、UI の描画、スレッド スケジュールの制御、およびアプリへの他の低レベル サービスの提供を行うシステムとフレームワーク コードが含まれています。 |
![]() |
セカンド レベル ノードの子はユーザー コード メソッドおよび非同期ルーチンで、セカンド レベル システムとフレームワーク コードによって呼び出される、または作成されます。 |
![]() |
メソッドの子ノードには、親メソッドを呼び出すためだけのデータが含まれます。 [外部コードの表示] がオフのとき、アプリ メソッドには [外部コード] ノードが含まれる場合もあります。 |
外部コード
コードによって実行されるシステム関数とフレームワーク関数は、外部コードと呼ばれます。 外部コード関数は、アプリの開始と停止、UI の描画、スレッドの制御、およびアプリへの他の低レベル サービスの提供を行います。 外部コードを確認することはほとんどないため、CPU 使用率呼び出しツリーはユーザー メソッドの外部関数を 1 つの [外部呼び出し] ノードにまとめます。
外部コードの呼び出しパスを表示するには、メインのレポート概要ページ (右側のウィンドウ) で、[設定] ドロップダウンから [マイ コードのみ表示] を選択解除し、[適用] を選択します。 ([設定] ドロップダウンは、詳細ビューではなく、メインのレポート概要ページで使用できます。)
スクリーンショット
コードによって実行されるシステム関数とフレームワーク関数は、外部コードと呼ばれます。 外部コード関数は、アプリの開始と停止、UI の描画、スレッドの制御、およびアプリへの他の低レベル サービスの提供を行います。 外部コードを確認することはほとんどないため、CPU 使用率呼び出しツリーはユーザー メソッドの外部関数を 1 つの [外部コード] ノードにまとめます。
外部コードの呼び出しパスを表示するには、診断レポートのメイン ページ (右側のウィンドウ) で、[フィルター] ドロップダウンから [外部コードの表示] を選択し、[適用] を選択します。 [CPU 使用率] ページの [呼び出しツリー] ビューで外部コードの呼び出しが展開されます。 ([フィルター] ドロップダウンは、詳細ビューではなくメインの診断ページで使用できます。)
[マイ コードのみ表示] を無効にすると、[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 使用率のデータを収集します。
関数ビューを開き、[呼び出し回数] 列が表示されるように設定されていることを確認します。
列が表示されない場合は、列の見出しを右クリックして表示する列を選びます。