ケース スタディ: パフォーマンスの問題を分離する (C#、Visual Basic、F#)

このケース スタディでは、Visual Studio プロファイリング ツールを使用して、サンプル ASP.NET アプリケーションのパフォーマンスの問題を特定して解決する方法を示します。 プロファイリング ツールの比較については、「どのツールを選択すればよいか」を参照してください。

学習内容:

  • Visual Studio プロファイリング ツールを使用してアプリケーションのパフォーマンスを分析する方法。
  • プロファイリング データを解釈してボトルネックを見つける方法。
  • .NET カウンター、呼び出し数、タイミング データを使用してコードを最適化するための実用的な戦略。

これらの手法を適用して、独自のアプリケーションを改善します。

ケーススタディにおけるパフォーマンス問題を特定する

サンプル ASP.NET アプリは、シミュレートされたデータベースに対してクエリを実行し、 診断サンプルに基づいています。

主なパフォーマンスの指標

  • CPU 使用率が低い: CPU はボトルネックではありません。
  • スレッド プールのスレッド数が多い: スレッド 数が着実に増加し、スレッド プールの不足を示します。
  • アプリケーションの応答が遅い: 使用可能なスレッドがないため、アプリの応答が遅くなります。

このケース スタディでは、Visual Studio プロファイリング ツールを使用してこれらの問題を特定して対処し、コードの高速化と効率化に役立ちます。

課題

これらの問題の修正には、いくつかの課題が含まれます。

  • ボトルネックの診断: パフォーマンスが低下した CPU 使用率が低いと、複数の原因が考えられます。 プロファイリング ツールを効果的に使用し、その出力を解釈することが不可欠です。
  • 知識とリソースの制約: プロファイリングと最適化には特定のスキルと経験が必要であり、常に使用できるとは限りません。

プロファイリング ツール、技術的な知識、慎重なテストを組み合わせた戦略的アプローチは、これらの課題を克服するための鍵となります。

戦略

このケース スタディのアプローチの概要を次に示します。

  • まず、パフォーマンス データの収集中に .NET カウンター メトリックを監視します。 Visual Studio の .NET カウンター ツールは、出発点として適しています。
  • 詳細な分析情報を得る場合は、呼び出し数やタイミング データ用の インストルメンテーション ツールなど、追加のプロファイリング ツールを使用してトレースを収集します。

データ収集には、次のタスクが必要です。

  • アプリをリリース ビルドに設定します。
  • パフォーマンス プロファイラー (Alt + F2) で .NET カウンター ツールを選択します。
  • アプリを起動し、トレースを収集します。

パフォーマンス カウンターを確認する

アプリの実行中に、.NET カウンター ツールでカウンターを確認します。 最初の調査では、注意が必要な主要なメトリックをいくつか次に示します。

  • CPU Usage。 このカウンターを見て、CPU 使用率が高いか低いかでパフォーマンスの問題が発生しているかどうかを確認します。 これは、特定の種類のパフォーマンスの問題の手がかりになる可能性があります。 例えば:
    • CPU 使用率が高い場合は、CPU 使用率ツールを使用して、コードを最適化できる可能性がある領域を特定します。 このチュートリアルについては、「ケース スタディ: コードの最適化に関する初心者向けガイド」を参照してください。
    • CPU 使用率が低い場合は、インストルメンテーション ツールを使用して、ウォール クロック時間に基づいて呼び出し数と平均関数時間を識別します。 これは、競合やスレッド プールの枯渇などの問題を特定するのに役立ちます。
  • Allocation Rate。 要求を提供する Web アプリの場合、レートはかなり安定している必要があります。
  • GC Heap Size。 このカウンターを見て、メモリ使用量が継続的に増加し、リークする可能性があるかどうかを確認します。 高いように見える場合は、メモリ使用量ツールのいずれかを使用します。
  • Threadpool Thread Count。 要求を処理する Web アプリの場合は、このカウンターを見て、スレッド数が安定しているか、安定した速度で上昇しているかどうかを確認します。

CPU Usage が低い一方で、ThreadPool Thread Count が比較的高い方法を示す例を次に示します。

.NET カウンター ツールに表示されているカウンターのスクリーンショット。

CPU 使用率が低いスレッド数が着実に増加している場合は、スレッド プールの不足を示す可能性があります。 スレッドプールは、新しいスレッドを生成し続けるように強制されます。 スレッド プールの枯渇は、プールに新しい作業項目を処理するための使用可能なスレッドがなく、アプリケーションの応答が遅くなることがよくあります。

CPU 使用率が低く、スレッド数が比較的多い場合に基づいて、スレッド プール不足の可能性のあるケースの理論に取り組んで、インストルメンテーション ツールの使用に切り替えます。

通話数とタイミング データを調査する

インストルメンテーション ツールのトレースを見て、スレッドで何が起こっているかを詳しく調べてみましょう。

インストルメンテーション ツールを使用してトレースを収集し、Visual Studio に読み込んだ後、まず最初に、概要データが表示される .diagsession レポート ページ を確認します。 収集されたトレースでは、レポートの [詳細を開く] リンク を使用し、次に[Flame Graph] を選択します。

インストルメンテーション ツールの Flame Graph のスクリーンショット。

Flame Graph の視覚エフェクトは、QueryCustomerDB 関数 (黄色で表示) がアプリの実行時間のかなりの部分を担当していることを示しています。

QueryCustomerDB 関数を右クリックし、[呼び出しツリーで表示] を選択します。

インストルメンテーション ツールのコール ツリーのスクリーンショット。

アプリの CPU 使用率が最も高いコード パスは、ホット パスと呼ばれます。 ホットパスフレームアイコン (ホットパスアイコンを示すスクリーンショット。) は、パフォーマンスの問題を素早く特定し、改善の可能性を見つけるのに役立ちます。

呼び出しツリー ビューでは、ホット パスに QueryCustomerDB 関数が含まれていることが確認できます。これは、潜在的なパフォーマンスの問題を示しています。

他の関数で費やされた時間に対して、 関数の Self 値と QueryCustomerDB 値は非常に高くなります。 Total と Avg Totalとは異なり、セルフ 値は他の関数で費やされた時間を除外するため、パフォーマンスのボトルネックを探すのに適しています。

ヒント

Self 値が高くなく、比較的低い場合は、QueryCustomerDB 関数によって呼び出された実際のクエリを調べたいと思うでしょう。

QueryCustomerDB 関数をダブルクリックして、関数のソース コードを表示します。

public ActionResult<string> QueryCustomerDB()
{
    Customer c = QueryCustomerFromDbAsync("Dana").Result;
    return "success:taskwait";
}

私たちは少し研究を行います。 あるいは、時間を節約し、Copilot に研究を任せることもできます。

Copilot を使用している場合は、コンテキスト メニューから [Copilot に質問する] を選択して次の質問を入力します。

Can you identify a performance issue in the QueryCustomerDB method?

ヒント

/optimize などのスラッシュ コマンドを使用して、Copilot に関する適切な質問を作成できます。

Copilot は、このコードが await を使用せずに非同期 API を呼び出していることを示します。 これは、スレッド プール不足の一般的な原因となり、スレッドをブロックする可能性のある sync-over-async コード パターンです。

解決するには、await を使用します。 この例では、Copilot は次のコード候補と説明を提供します。

public async Task<ActionResult<string>> QueryCustomerDB()
{
    Customer c = await QueryCustomerFromDbAsync("Dana");
    return "success:taskwait";
}

データベース クエリに関連するパフォーマンスの問題が発生した場合は、Database ツール を使用して、特定の呼び出しが遅いかどうかを調査できます。 このデータは、クエリを最適化する機会を示している可能性があります。 データベース ツールを使用してパフォーマンスの問題を調査する方法を示すチュートリアルについては、「ケース スタディ: コードの最適化に関する初心者向けガイド」を参照してください。 データベース ツールは、ADO.NET または Entity Framework Core を使用した .NET Core をサポートします。

Visual Studio で個々のスレッド動作の視覚化を取得するには、デバッグ中に Parallel Stacks ウィンドウを使用できます。 このウィンドウには、個々のスレッドと、待機しているスレッド、待機中のスレッド、デッドロック に関する情報が表示されます。

スレッド プールの枯渇の詳細については、「スレッド プールの不足を検出する」を参照してください。

次の手順

次の記事とブログ記事では、Visual Studio パフォーマンス ツールを効果的に使用する方法を学習するのに役立つ詳細情報を提供します。