適用対象: .NET Core 2.1、.NET Core 3.1、.NET 5
この記事では、dotnet-dump ツールを使用して .NET Core ダンプをキャプチャおよび分析し、 dotnet-gcdump
を使用して Linux で GC 関連レポートを生成する方法について説明します。
前提条件
これらのトラブルシューティング ラボに従う最小要件は次のとおりです。
- 低 CPU および高 CPU パフォーマンスの問題とクラッシュの問題を示す ASP.NET Core アプリケーション。
- コア ダンプ ファイルが開かれたときに SOS 拡張機能を読み込むようインストールおよび構成された lldb デバッガー。
このシリーズの前の部分に従っている場合は、次のセットアップを準備しておく必要があります。
- Nginx は、次の 2 つの Web サイトをホストするように構成されています。
- 1 つ目は、 myfirstwebsite ホスト ヘッダー (
http://myfirstwebsite
) を使用して要求をリッスンし、ポート 5000 でリッスンするデモ ASP.NET Core アプリケーションに要求をルーティングします。 - 2 つ目は、 buggyamb ホスト ヘッダー (
http://buggyamb
) を使用して要求をリッスンし、ポート 5001 でリッスンする 2 番目の ASP.NET Core サンプル バグのあるアプリケーションに要求をルーティングします。
- 1 つ目は、 myfirstwebsite ホスト ヘッダー (
- ASP.NET コア アプリケーションは、サーバーが再起動されたとき、またはアプリケーションが応答を停止したときに自動的に再起動するサービスとして実行されている必要があります。
- Linux ローカル ファイアウォールが有効になっており、SSH トラフィックと HTTP トラフィックを許可するように構成されています。
Note
セットアップの準備ができていない場合は、「Part 2 Core アプリ ASP.NET 作成して実行する」に進みます。
このラボの目標
Lab 2.2 では、ProcDump を使用してダンプ ファイルをキャプチャし、手動またはメモリ使用量の監視によって、ProcDump を使用してコア ダンプ ファイルをキャプチャするようにテストしました。
このパートでは、dotnet-dump を使用して、ネイティブ デバッガーなしでコア ダンプ ファイルをキャプチャおよび分析する方法について説明します。 次に、 dotnet-gcdump
を使用して、Windows ベースのコンピューターで開くことができる GC 関連のレポートを生成する方法について説明します。
Dotnet-dump
dotnet-dump は、Linux 上の lldb などのネイティブ デバッガーを使用せずにコア ダンプ ファイルを収集および分析するもう 1 つの方法です。 このツールを使用すると、クラッシュやガベージ コレクター (GC) 関連の問題を分析するために SOS コマンドを実行することもできます。 Dotnet-dump は、.NET Core 3.0 SDK 以降のバージョンでのみ使用できます。
Note
Dotnet-dump はネイティブ デバッガーではありません。 そのため、ネイティブ スタック フレームの表示など、一部の機能は、このツールでは使用できません。
dotnet-dump をインストールしていない場合は、次のコマンドを実行してインストールできます。
dotnet tool install -g dotnet-dump
コア ダンプ ファイルを手動でキャプチャするには、 dotnet-dump collect
コマンドを使用します。 たとえば、dotnet-dump collect -p 11724
のようにします。 ツールは、createdump または ProcDump を使用して収集したのと同じコア ダンプ ファイルを収集します。
dotnet-dump の最も重要な機能は、lldb と同じように、.NET Core ダンプ ファイルを開いて SOS コマンドを実行するために使用できることです。 dotnet-dump を使用してダンプ ファイル bu を分析できるようにするには、シンボルを設定し、SOS 拡張機能をインストールする必要があります。
Note
以前に lldb を使用していた場合は、シンボルが既に設定され、SOS がインストールされている必要があります。 そのため、シンボルをもう一度ダウンロードしなくても、同じ .NET Core バージョンのダンプ ファイルを開くことができるはずです。 シンボルがまだダウンロードされていない別の .NET Core バージョン のダンプ ファイルを開いた場合は、分析を開始する前に、そのバージョンの .NET Core のシンボルをダウンロードする必要があります。
dotnet-dump を使用してコア ダンプ ファイルを収集する
dotnet-dump を使用してコア ダンプ ファイルを収集するには、 dotnet-dump collect <PID>
コマンドを使用します。 PID の決定は、この時点で簡単に行う必要があります。 ただし、ヘルプが必要な場合は、このコマンドに ps
パラメーターが含まれます。 dotnet-dump ps
コマンドは、ダンプ ファイルを収集できる dotnet プロセスを一覧表示します。
dotnet-dump ps
コマンドを実行しようとすると、予期しない結果が発生します。
この一覧には、2 つのプロセスが表示されます。 ただし、そのうちの 1 つは昇格されたプロセスとして表示され、そのパスは dotnet-dump
ps コマンドでは決定できません。 そのパスを見つけるには、 cat /proc/<PID>/cmdline
コマンドを実行して、プロセスのコマンド ライン情報を調べます。
Note
このコマンドでは、次の出力例に示すように、 <PID>
をターゲット プロセスの実際のプロセス ID に置き換えます。 前のセクションの特殊な /proc/ ディレクトリを思い出すことができます。Linux のプロセスは、そのディレクトリの下の別のフォルダー (プロセス ID の名前を持つ) と見なすことができます。 /proc/<PID>/ ディレクトリ構造を調べることで、プロセスに関するすべての詳細を確認できます。
このスクリーンショットに示すように、最初のコマンド (cat /proc/6164/cmdline
) の出力は、これが Core アプリケーション ASP.NET 初めてのデモであることを示しています。 2 番目のコマンド (cat /proc/15586/cmdline
) の出力は、これがバグのあるアプリケーションであることを示します。
dotnet-dump ps
コマンドはプロセス パスを取得できませんでしたが、トラブルシューティングに必要なダンプ ファイルを生成できる必要があります。 dotnet-dump collect
コマンドを使用して、コア ダンプ ファイルをキャプチャしてみてください。 まず、ツールでプロセス パスを表示できたデモ アプリケーションを試します。 dotnet-dump collect -p 6164
を実行します (演習を試すとプロセス PID が異なります)。
メモリ ダンプ ファイルの生成に成功しました。 ここで、 dotnet-dump ps
コマンドを使用したときにツールでプロセス パスを一覧表示できなかったバグのあるアプリケーションのコア ダンプ ファイルを収集してみてください。 dotnet-dump collect -p 15586
実行し、予期せず失敗します。
次のエラー メッセージが返されます。
(13): アクセス許可が拒否されました /tmp/dotnet-diagnostic-15586-25444688-socket
dotnet-dump ps
コマンドがプロセス パスを取得できなかったことに気付いた場合、コア ダンプ ファイルを生成しようとすると失敗する可能性があります。
前のエラー メッセージから、アクセス許可の問題が発生していることを確認できます。 しかし、2 つのプロセスの違いは何ですか。1 つ目は .NET 5 サンプル アプリケーションをホストし、2 つ目は .NET Core 3 アプリケーションをホストしていますか? 各プロセスのサービス ファイルを比較します。 相対的に簡単に違いを見つけることができます。各プロセスを実行するユーザー アカウントは異なります。
一覧の左側は、すべてが正常に動作する最初のデモ アプリケーションに対応し、アプリケーションは <User Name> (または環境を設定してログインしたときに使用したユーザー アカウント) として実行されます。 右側は、ダンプ ファイルの収集に失敗したバグのあるアプリケーションに対応します。 アプリケーションは www-data ユーザーとして実行されます。
この問題の解決策については、公式の GitHub ページで説明します。
要約すると、ログインに使用したアカウントとは異なるユーザーとしてサービス プロセスを実行している場合は、次のように dotnet-dump collect
コマンドを実行する必要があります。
コマンドの形式を次に示します。
sudo -H -u <user name of service> bash -c "<full path to dotnet tools>/dotnet-dump collect -p <PID> -o <output path>"
dotnet-dump ツールの完全パスは、 whereis dotnet-dump
コマンドを使用して確認できます。
出力パスは、ユーザーが書き込みアクセス許可を持つディレクトリである必要があります。 通常は、 /tmp ディレクトリの下にディレクトリを作成し、後でダンプ ファイルをホーム ディレクトリにコピーできます。
dotnet-dump を使用してコア ダンプ ファイルを開いて分析する
この演習では、新しいダンプ ファイルをキャプチャする必要はありません。 代わりに、createdump を使用してキャプチャした前のダンプ ファイルのいずれかを開くことができます。 必要に応じて、dotnet-dump を使用してキャプチャしたコア ダンプ ファイルを開くことができます。
dotnet-dump を使用してダンプ ファイルを開くには、 dotnet-dump analyze ~/dumps/coredump.manual.2.11724
を実行します (メモリ ダンプ ファイルの名前はコンピューター上で異なります)。 これは、lldb で前に使用したのと同じマネージド デバッガー エンジンです。 シンボルが正しく構成されていて、SOS が正しくインストールされている場合は、lldb を使用する場合と同じように、任意の SOS コマンドを実行できます。 次の一覧では、 clrstack
コマンドの動作を確認できます。
次の 2 つの点に注意してください。
- これはネイティブ デバッガーではないので、前に lldb で使用するように指示されたメモリ読み取りコマンドなど、lldb ネイティブ デバッガー コマンドを実行することはできません。 SOS コマンドのみを実行できます。
- 自動補完が機能していません。 lldb では、コマンドの入力を開始し、コマンド ラインとシェルと同じように、 TAB キーを押してコマンドをオートコンプリートできます。 この機能は dotnet-dump では機能しません。 ただし、これはトレーニングに影響を与えるべきではありません。
コア ダンプ ファイルを開いている間に、この機会に新しい SOS コマンドをいくつか練習してください。
ダンプ内の CPU 使用率を確認するにはどうすればよいですか? threadpool
コマンドは、この情報を明らかにするのに役立つ場合があります。 "サーバーの CPU 使用率の合計" が報告されますが (デバッグ中のプロセスだけでなく)、メモリ ダンプ ファイルが生成された時点でのコンピューターでのリソース消費量の一般的な概念が提供されます。 次のスクリーンショットは、サーバーの合計 CPU 使用率が約 94% であることを示しています。
Note
これらのリストの作成に使用されたサーバーには、2 つの CPU が装備されていました。 これが、このようなレポートを生成する理由です。
同じ出力にはスレッド プールの構成も示されており、前の一覧では、7 つのワーカー スレッドが使用可能で、そのうちの 6 つのスレッドが実行されていました。 この情報は、スレッド プールの構成の問題をトラブルシューティングするときに役立ちます。
実行中のすべてのスレッドの呼び出し履歴をグループ化し、Visual Studio Parallel Stacks パネルと同様に、マージされた表示を表示しますか? pstacks
を実行して、同様の結果を取得します。
使用可能な SOS コマンドの理解を深めるために、SOS ヘルプを開き、各コマンドを個別に確認して、SOS デバッグの機能について理解します。
Dotnet-dump は、lldb をインストールするオプションがない場合に便利です。 トレーニングは引き続き、GC ヒープを分析するための別のアプローチを導入することで行われます。
Dotnet-gcdump
Dotnet-gcdump も便利なツールです。 .NET Core 3.1 以降のバージョンで使用できます。
このツールの背後にある考え方は、主にマネージド ヒープを確認する多くのシナリオで調査を完了するために、完全なプロセス ダンプは必要ないということです。 では、ヒープ情報をキャプチャして、それに関するレポートを生成するだけではなぜですか? 最も重要なのは、このツールによって生成される GC ダンプ ファイルは移植可能であり、Windows コンピューターで分析できることです。 この種類のダンプ ファイルには GC ヒープ情報のみが含まれているため、lldb で開いてスレッドまたはスレッド呼び出し履歴を調査することはできません。 ただし、PerfView または Visual Studio で開くことができます。
これは有望に聞こえるかもしれませんが、... 注意する必要がある点が 1 つあります。 Dotnet-gcdump
は、プロセスで Gen 2 GC コレクションをトリガーして、必要なデータを収集します。 運用環境では、このツールを慎重に使用してください。 あなたが確実にしなければならないことがわかっている場合を除き、それを使用しないでください。
このツールを使用する必要がある場合は、 プロセスが既に応答しない (ハングしている) 状態で、状況から回復するものがない場合は、アプリケーションを再起動する予定です。 その後、再起動前に gcdump をキャプチャして、後の段階で分析する情報のセットを少なくとも 1 つ取得できます。
このツールによってキャプチャされる情報は、次のタスクに役立ちます。
- ヒープの種類別にオブジェクトの数を比較します。
- オブジェクト ルートを分析します。
- どのオブジェクトがどの型に対する参照を持っているかを決定します。
- ヒープ上のオブジェクトに関するその他の統計分析。
このツールをまだインストールしていない場合は、今すぐインストールしてください。 次のコマンドを実行するだけで済みます。
dotnet tool install --global dotnet-gcdump
dotnet-gcdump コマンドを使用して gcdump を収集する
dotnet-dump ツールに適用された dotnet-gcdump
にも同じルールが適用されます。別のユーザーに対してプロセスを実行する場合は、次の形式でコマンドを実行する必要があります。
sudo -H -u <user name of service> bash -c "<full path to dotnet tools>/dotnet-gcdump collect -p <PID> -o <output path>"
このコマンドを使い慣れていない場合は、「 collecting core dump files by using dotnet-dump 」セクションを参照してください。
これで、ツールを使用してプロセス情報を収集するために必要なものがすべて揃いました。 目的は、コア ダンプ ファイルを使用して行ったのと同じように、2 つのデータ セットを収集することです。 ターゲット プロセスは、別のユーザーに対して再度実行されます。 したがって、スタートアップ コマンドには "bash" 形式を使用する必要があります。
次に手順を示します。
ASP.NET Core Web サイトに含まれている Load Generator ツールを使用して、Slow ページに対して 6 つの要求を実行して、パフォーマンスの問題を再現します。
次のコマンドを実行して、最初の gcdump を収集します。
sudo -H -u www-data bash -c "/home/<User Name>/.dotnet/tools/dotnet-gcdump collect -p 15586 -o /tmp/gcreport1.gcdump"
注: このコマンドでは、PID を独自のものに置き換えます。
5 ~ 10 秒待ってから、次のコマンドを実行して 2 番目の gcdumpby を収集します。
sudo -H -u www-data bash -c "/home/<User Name>/.dotnet/tools/dotnet-gcdump collect -p 15586 -o /tmp/gcreport2.gcdump
注: このコマンドでは、PID を元の PID に置き換えます。
パフォーマンスの問題のトラブルシューティングを行っていることを忘れないでください。 マネージド ヒープが時間の経過とどのように進化したかを比較できるように、複数のデータ セットを使用することをお勧めします。 これらのコマンドの結果として、2 つの gcdump ファイルが生成されます。
gcdump ファイルからレポートを作成する
両方の gcdump ファイルを Windows ベースのコンピューターにコピーし、Visual Studio 2019 で開きます。 次のスクリーンショットは、この一覧で取得された両方の gcdump ファイルの比較結果を示しています。 ご覧のように、 String オブジェクト型の値には大きな違いがあります。 オブジェクトに関するルート情報を取得することもできます。
これは役に立つ情報です。
または、gcdump レポートを PerfView で開く方法もあります。
マネージド ヒープのみを確認する必要がある場合は、これが最も高速なオプションになる可能性があります。 前に説明したように、プロセスで完全な GC がトリガーされ、長い一時停止が発生する可能性があるため、運用環境で dotnet-gcdump
を使用する場合は注意が必要です。 このツールは、メモリの問題をトラブルシューティングするときに必要な場合にのみ、慎重に運用環境で使用してください。