次の方法で共有


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

プロファイリング ツールを使用して、パフォーマンスの問題を調査し、問題の領域を特定します。 このケース スタディでは、パフォーマンスの問題があるサンプル アプリケーションを使用して、プロファイリング ツールを使用して効率を向上させる方法を示します。 プロファイリング ツールを比較する場合は、「どのツールを選択すればよいか」を参照してください。

このケース スタディでは、次のトピックについて説明します。

  • Visual Studio プロファイリング ツールを使用してアプリケーションのパフォーマンスを分析する方法。
  • これらのツールによって提供されるデータを解釈して、パフォーマンスのボトルネックを特定する方法。
  • .NET カウンター、呼び出し数、タイミング データに重点を置いて、コードを最適化するための実用的な戦略を適用する方法。

次に、これらの手法を独自のアプリケーションに適用して、効率とコスト効率を高めます。

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

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

サンプル アプリケーションの主なパフォーマンスの問題は、非効率的なコーディング パターンにあります。 アプリケーションには、効率に大きな影響を与えるパフォーマンスのボトルネックがあります。 この問題には、次の現象が含まれます。

  • 低 CPU 使用率: アプリケーションは CPU 使用率が低く、CPU がボトルネックではないことを示します。

  • スレッドプールスレッド数が: スレッド数が比較的に高く、着実に上昇していることは、スレッドプールの枯渇を示唆しています。

  • アプリケーションの応答が遅い: 新しい作業項目を処理するために使用可能なスレッドがないため、アプリケーションの応答が遅くなります。

このケース スタディでは、Visual Studio のプロファイリング ツールを使用してアプリケーションのパフォーマンスを分析することで、これらの問題に対処することを目的としています。 アプリケーションのパフォーマンスを向上できる場所と方法を理解することで、開発者は最適化を実装してコードをより迅速かつ効率的にすることができます。 最終的な目標は、アプリケーションの全体的なパフォーマンスを向上させ、実行の効率とコスト効率を高めることです。

課題

サンプルの .NET アプリケーションでパフォーマンスの問題に対処するには、いくつかの課題があります。 これらの課題は、パフォーマンスのボトルネックの診断の複雑さに起因します。 説明されている問題を解決する際の主な課題は次のとおりです。

  • パフォーマンスのボトルネックの診断: 主な課題の 1 つは、パフォーマンスの問題の根本原因を正確に特定することです。 CPU 使用率が低いとパフォーマンスが低下すると、複数の要因が発生する可能性があります。 開発者は、プロファイリング ツールを効果的に使用してこれらの問題を診断する必要があります。これには、これらのツールのしくみと出力の解釈方法を理解する必要があります。

  • 知識とリソースの制約: Teams は、知識、専門知識、リソースに関連する制約に直面する可能性があります。 アプリケーションのプロファイリングと最適化には特定のスキルと経験が必要であり、すべてのチームがこれらのリソースにすぐにアクセスできるわけではありません。

これらの課題に対処するには、プロファイリング ツールの効果的な使用、技術的な知識、慎重な計画とテストを組み合わせた戦略的アプローチが必要です。 このケース スタディは、開発者がこのプロセスをガイドし、これらの課題を克服し、アプリケーションのパフォーマンスを向上させるための戦略と分析情報を提供することを目的としています。

戦略

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

  • パフォーマンス データの収集中に .NET カウンター メトリックを見て調査を開始します。 CPU 使用率ツールと同様に、Visual Studio の .NET カウンター ツールも、パフォーマンス調査の出発点として適しています。
  • 次に、問題の特定やパフォーマンスの向上に役立つ追加の分析情報を得るために、他のプロファイリング ツールのいずれかを使用してトレースを収集することを検討してください。 たとえば、インストルメンテーション ツールを使用して、呼び出し数とタイミング データを確認します。

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

  • アプリをリリース ビルドに設定する。
  • パフォーマンス プロファイラーから .NET カウンター ツールを選択します (Alt + F2)。 (後の手順にはインストルメンテーション ツールが含まれます)。
  • パフォーマンス プロファイラーからアプリを起動し、トレースを収集します。

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

アプリの実行中に、.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 関数が含まれていることが確認できます。これは、潜在的なパフォーマンスの問題を示しています。

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

ヒント

セルフ値が高い値ではなく比較的低い場合は、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 パフォーマンス ツールを効果的に使用する方法を学習するのに役立つ詳細情報を提供します。