私は最近、生産作業に ANTS プロファイリング ツールを使い始めました。その素晴らしさに驚かされることは別として、私は彼らがどのように機能するのか疑問に思わずにはいられませんでした. たとえば、最も便利な機能の 1 つを使用すると、実行中のプログラムのグローバル ルートを、さまざまな型の値への参照の数とともに視覚化できます。
このツールはどのようにしてその情報を取得しますか?
(完全な開示: 私は Visual Studio Profiler チームに所属していますが、以下の情報は公開されています)
これを行うには、対象のプロセス内で実行される CLR プロファイラーを作成します。COR_PROFILER
CLR プロファイラーは、およびCOR_PROFILING_ENABLED
環境変数が設定されたときにランタイムによってインスタンス化される C++ COM オブジェクトです(こちらを参照)。2 つの主なCLR プロファイリング インターフェイスがあります。具体的にはICorProfilerCallback
とICorProfilerInfo
です。 ICorProfilerCallback
サブスクライブする特定のイベント (モジュールの読み込み、関数の JIT コンパイル、スレッドの作成、GC イベント) について通知するために CLR が使用するものであり、ICorProfilerInfo
スレッド、モジュール、型、メソッドに関する追加情報を取得するためにプロファイラーで使用できます。読み込まれたアセンブリのメタデータ。このインターフェイスは、割り当てられた型に関するシンボル情報を取得するために使用できるものです。
プロファイラーがインプロセスの状態で、強制的に GC を通過させることができますICorProfilerInfo::ForceGC
。GC が完了すると、プロファイラーは 経由ICorProfilerCallback2::GarbageCollectionFinished
で通知を受け取り、 経由でルート参照を取得しますICorProfilerCallback2::RootReferences2
。ルート参照情報を と組み合わせるとICorProfilerCallback::ObjectReferences
、.NET アプリケーションの完全なオブジェクト参照グラフを取得できます。
ICorProfilerCallback::ObjectAllocated
コールバックを使用して個々の CLR オブジェクトがいつ作成されるかを判断することで、より多くのリアルタイム情報を取得できます。ただし、割り当てられたオブジェクトごとに少なくとも追加の関数呼び出しが発生するため、これにはコストがかかる可能性があります。ObjectID
独自の内部 ID に割り当てられた CLR をマッピングすることで、個々のオブジェクトを追跡できます。特定のObjectID
オブジェクトの は、圧縮中にオブジェクトが移動する可能性があるガベージ コレクションが発生すると変更される可能性があるため、一時的なポインターです。このプロセスをここに示します。からの情報を使用して、ICorProfilerCallback::MovedReferences
移動するオブジェクトを追跡できます。
上記のコールバックをアクティブにするには、CLR プロファイリング API に関心があることを伝える必要があります。これは、 を呼び出すときにイベント フラグの一部としてCOR_PRF_MONITOR_GC
とを指定することで実行できます。COR_PRF_MONITOR_OBJECT_ALLOCATED
ICorProfilingInfo::SetEventMask
David Broman は CLR プロファイラーの開発者であり、彼のブログには、プロファイリング全般に関する有益な情報がたくさんあります。
ANTS のようなプロファイラーは、CLR 自体が提供する「プロファイリング API」を使用します。これにより、CLR 内で何が起こっているかを簡単に知ることができます。たとえば、オブジェクトが割り当てられたときに発生する API コールバック メソッドがあり、適切にObjectAllocated()という名前が付けられています。同様に、メソッドが入力されたとき、スレッドが作成されたときなどのイベントがあります。
元のプロファイリング API は ICorProfilerCallback と呼ばれます。それ以降のバージョンは、CoreProfilerCallback2 および CoreProfilerCallback3 と呼ばれます。これらの名前をググると、探している答えが正確に見つかります。codeproject では、実用的な例を見ることができます:カスタム .NET プロファイラーの作成
最後の注意: API は、C# や VB.NET などのマネージ コードからは使用できません。C や C++ などのアンマネージ コードからのみ使用できます。したがって、C# アプリは、この API を使用して、たとえば、独自の動作やオブジェクトを調べることはできません。