PerfCollect を使用して .NET アプリケーションをトレースする
この記事の対象: ✔️ .NET Core 2.1 SDK 以降のバージョン
Linux でパフォーマンスの問題が発生した場合は、perfcollect
でトレースを収集することにより、パフォーマンスの問題が発生したときにコンピューターで何が起きていたかに関する詳細な情報を収集できます。
perfcollect
は Bash スクリプトであり、Linux Trace Toolkit: next generation (LTTng) を利用して、ランタイムまたは任意の EventSource から書き込まれたイベントを収集すると共に、perf を利用してターゲット プロセスの CPU サンプルを収集します。
コンピューターを準備する
perfcollect
を使用してパフォーマンス トレースが収集されるようコンピューターを準備するには、以下の手順のようにします。
Note
コンテナー内からキャプチャする場合は、コンテナーに適切な機能が必要です。 最低限必要な機能は、PERFMON
と SYS_PTRACE
です。 最小セットでキャプチャが失敗した場合は、コンテナーに SYS_ADMIN
機能を追加してください。 PerfCollect を使用してコンテナー内のアプリケーションをトレースする方法の詳細については、「コンテナーでの診断の収集」を参照してください。
perfcollect
をダウンロードします。curl -OL https://aka.ms/perfcollect
スクリプトを実行できるようにします。
chmod +x perfcollect
トレースの前提条件をインストールします。これらは実際のトレース ライブラリです。
sudo ./perfcollect install
これにより、次の前提条件がコンピューターにインストールされます。
perf
: Linux Performance Events サブシステムと、コンパニオン ユーザーモード コレクションおよびビューアー アプリケーション。perf
は Linux カーネル ソースの一部ですが、通常は既定ではインストールされません。LTTng
: 実行時に CoreCLR によって生成されるイベント データをキャプチャするために使用されます。 その後、このデータを使用して、GC、JIT、スレッド プールなどのさまざまなランタイム コンポーネントの動作が分析されます。
最新のバージョンの .NET Core および Linux perf ツールでは、フレームワーク コードのためのメソッド名の自動解決がサポートされています。
ネイティブ ランタイム DLL (libcoreclr.so など) のメソッド名の解決の場合は、perfcollect
によってデータの変換時にそれらのシンボルが解決されますが、それが行われるのはこれらのバイナリのシンボルが存在する場合だけです。 詳細については、ネイティブ ランタイムのシンボルの取得に関するセクションを参照してください。
トレースを収集する
2 つのシェルを使用できるようにします。1 つはトレースの制御用で ( [Trace] と呼びます)、もう 1 つはアプリケーションの実行用です ( [App] と呼びます)。
[Trace] 収集を開始します。
sudo ./perfcollect collect sampleTrace
予想される出力:
Collection started. Press CTRL+C to stop.
[App] 次の環境変数を使用して、アプリケーションのシェルを設定します。これにより、CoreCLR のトレース構成が有効になります。
export DOTNET_PerfMapEnabled=1 export DOTNET_EnableEventLog=1
注意
.NET 7 でアプリを実行するとき、前述の環境変数に加え、
DOTNET_EnableWriteXorExecute=0
も設定する必要があります。 次に例を示します。export DOTNET_EnableWriteXorExecute=0
注意
.NET 6 では、.NET の実行時の動作を構成する環境変数のプレフィックスが、
COMPlus_
ではなくDOTNET_
に標準化されています。 ただし、プレフィックスCOMPlus_
は引き続き機能します。 以前のバージョンの .NET ランタイムを使用している場合は、環境変数にCOMPlus_
プレフィックスをまだ使用する必要があります。[App] アプリを実行します。パフォーマンスの問題をキャプチャするために必要な限り実行させておきます。 正確な長さは、調査する必要があるパフォーマンスの問題が発生した時間帯を十分に把握できる限り、必要なだけ短くできます。
dotnet run
[Trace] 収集を停止します。Ctrl + C キーを押します。
^C ...STOPPED. Starting post-processing. This may take some time. Generating native image symbol files ...SKIPPED Saving native symbols ...FINISHED Exporting perf.data file ...FINISHED Compressing trace files ...FINISHED Cleaning up artifacts ...FINISHED Trace saved to sampleTrace.trace.zip
圧縮されたトレース ファイルが、現在の作業ディレクトリに格納されます。
トレースを表示する
収集されたトレースを表示するには、いくつかのオプションがあります。 トレースは、Windows で PerfView を使用すると最も適切に表示されますが、PerfCollect
自体または TraceCompass
を使用して Linux で直接表示することもできます。
PerfCollect を使用してトレース ファイルを表示する
Perfcollect 自体を使用して、収集したトレースを表示できます。 これを行うには、次のコマンドを使用します。
./perfcollect view sampleTrace.trace.zip
このようにすると、既定では、perf
を使用しているアプリケーションの CPU トレースが表示されます。
LTTng
によって収集されたイベントを見るには、フラグ -viewer lttng
を渡して個々のイベントを表示します。
./perfcollect view sampleTrace.trace.zip -viewer lttng
このようにすると、babeltrace
ビューアーを使用してイベントのペイロードが出力されます。
# [01:02:18.189217659] (+0.020132603) ubuntu-xenial DotNETRuntime:ExceptionThrown_V1: { cpu_id = 0 }, { ExceptionType = "System.Exception", ExceptionMessage = "An exception happened", ExceptionEIP = 139875671834775, ExceptionHRESULT = 2148734208, ExceptionFlags = 16, ClrInstanceID = 0 }
# [01:02:18.189250227] (+0.020165171) ubuntu-xenial DotNETRuntime:ExceptionCatchStart: { cpu_id = 0 }, { EntryEIP = 139873639728404, MethodID = 139873626968120, MethodName = "void [helloworld] helloworld.Program::Main(string[])", ClrInstanceID = 0 }
PerfView を使用してトレース ファイルを開く
CPU サンプルとイベント両方の集約ビューを表示するには、Windows コンピューターで PerfView
を使用します。
trace.zip ファイルを Linux から Windows コンピューターにコピーします。
https://aka.ms/perfview から PerfView をダウンロードします。
PerfView.exe を実行する
PerfView.exe <path to trace.zip file>
PerfView により、トレース ファイルに含まれるデータに基づいてサポートされるビューの一覧が表示されます。
CPU の調査の場合は、 [CPU stacks](CPU スタック) を選択します。
GC の詳細な情報の場合は、 [GCStats](GC 統計) を選択します。
プロセス、モジュール、メソッドごとの JIT の情報の場合は、 [JITStats](JIT 統計) を選択します。
必要な情報のビューがない場合は、生のイベント ビューでイベントを検索してみることができます。 [Events](イベント) を選択します。
PerfView でのビューの解釈方法の詳細については、ビュー自体のヘルプ リンクを参照するか、PerfView のメイン ウィンドウで [ヘルプ] > [ユーザー ガイド] の順に選択してください。
注意
System.Diagnostics.Tracing.EventSource API を使用して書き込まれたイベント (フレームワークからのイベントを含む) は、プロバイダー名の下に表示されません。 代わりに、Microsoft-Windows-DotNETRuntime
プロバイダーの下に EventSourceEvent
イベントとして書き込まれ、そのペイロードは JSON でシリアル化されます。
Note
メソッドの名前とコールスタックに [unknown] /memfd:doublemapper
フレームがある場合、perfcollect で追跡するアプリを実行する前に DOTNET_EnableWriteXorExecute=0
を設定します。
TraceCompass を使用してトレース ファイルを開く
Eclipse TraceCompass は、トレースを表示するために使用できるもう 1 つのオプションです。 TraceCompass
は Linux マシンでも動作するので、トレースを Windows コンピューターに移動する必要はありません。 TraceCompass
を使用してトレース ファイルを開くには、ファイルを解凍する必要があります。
unzip myTrace.trace.zip
perfcollect
によって収集された LTTng トレースは、lttngTrace
内のサブディレクトリに CTF ファイル形式で保存されます。 具体的には、CTF ファイルは lttngTrace/auto-20201025-101230\ust\uid\1000\64-bit\
のようなディレクトリに格納されます。
File -> Open Trace
を選択して metadata
ファイルを選択することにより、TraceCompass
で CTF トレースファイルを開くことができます。
詳細については、TraceCompass
のドキュメントを参照してください。
ネイティブ ランタイムのシンボルを取得する
ほとんどの場合、関心があるのは独自のコードであり、それは perfcollect
によって既定で解決されます。 場合によっては、NET DLL の内部で起こっていること (最後のセクションの内容) を確認すると役に立つことがありますが、ネイティブ ランタイム dll (通常は libcoreclr.so) で何が起こっているかは興味深いものです。 perfcollect
によってデータの変換時にこれらに対するシンボルが解決されますが、これらのネイティブ DLL のシンボルが存在する場合 (および、それらが対象のライブラリの隣にある場合) に限られます。
これを行う dotnet-symbol という名前のグローバル コマンドがあります。 dotnet-symbol を使用してネイティブ ランタイム シンボルを取得するには:
dotnet-symbol
をインストールします。dotnet tool install -g dotnet-symbol
シンボルをダウンロードします。 インストールされている .NET Core ランタイムのバージョンが 2.1.0 の場合は、次のコマンドを実行します。
mkdir mySymbols dotnet symbol --symbols --output mySymbols /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0/lib*.so
シンボルを正しい場所にコピーします。
sudo cp mySymbols/* /usr/share/dotnet/shared/Microsoft.NETCore.App/2.1.0
適切なディレクトリへの書き込みアクセス権がないためにこの操作を実行できない場合は、
perf buildid-cache
を使用してシンボルを追加できます。
その後、perfcollect
を実行するときに、ネイティブ dll のシンボル名を取得する必要があります。
Docker コンテナー内で収集する
コンテナー環境で perfcollect
を使用する方法の詳細については、「コンテナーでの診断の収集」を参照してください。
収集オプションについての詳細情報
診断のニーズに合わせて、perfcollect
を使用して次のオプションのフラグを指定できます。
特定の期間について収集する
特定の期間についてトレースを収集する場合は、-collectsec
オプションに続けて、トレースを収集する合計秒数を数値で指定できます。
threadtime のトレースを収集する
-threadtime
と共に perfcollect
を指定すると、スレッドごとの CPU 使用率データを収集できます。 これにより、各スレッドが CPU 時間を費やしていた場所を分析できます。
マネージド メモリとガベージ コレクターのパフォーマンスのトレースを収集する
次のオプションを使用すると、ランタイムから特に GC イベントを収集できます。
perfcollect collect -gccollectonly
GC 収集イベントの最小セットのみを収集します。 これは、ターゲット アプリのパフォーマンスへの影響が最も少ない、最も詳細度の低い GC イベント収集プロファイルです。 このコマンドは PerfView の PerfView.exe /GCCollectOnly collect
コマンドと似ています。
perfcollect collect -gconly
JIT、ローダー、例外イベントを使用して、より詳細な GC 収集イベントを収集します。 これにより、より詳細なイベント (割り当て情報や GC 結合情報など) が要求され、-gccollectonly
オプションよりもターゲット アプリのパフォーマンスに大きく影響します。 このコマンドは PerfView の PerfView.exe /GCOnly collect
コマンドと似ています。
perfcollect collect -gcwithheap
最も詳細な GC コレクション イベントを収集します。これにより、ヒープの存続と移動も追跡されます。 これにより、GC の動作を詳細に分析できますが、各 GC に 2 倍以上の時間がかかるおそれがあるため、パフォーマンス コストが高くなります。 運用環境でトレースするときにこのトレース オプションを使用した場合のパフォーマンスへの影響を理解しておくことをお勧めします。
.NET