トレース プロファイラーは、関数の開始と終了をログに記録します。また、呼び出し履歴のグラフを作成することもできます。 この機能の実装を支援するために、.NET Framework には、グローバル静的関数のプロファイルが用意されています。この機能には、enter/leave/tailcall (ELT) API と呼ばれる一連の関連する関数およびインターフェイスがあります。
.NET Framework Version 4 より前、ELT 関数を使用するトレース プロファイラーでは、小さいマネージ関数の数が増えるにつれパフォーマンスが低下しました。.NET Framework 4 以降では、ELT Version 3 (ELT3) API を使用して、ELT のパフォーマンスを向上させることができます。これは、引数または戻り値の検査の必要がない場合に特に有効です。 次の点でパフォーマンスが向上します。
ELT の高速パス関数では、Just-In-Time (JIT) コンパイル コードのサイズが小さくなります。
必要な引数 ELT の数が最小限になり、プロファイラーに渡すパラメーターに必要なスタック領域が減ります。
スタック フレームのセットアップと引数の検査は必要なとき以外行われないので、実行速度が上がります。
フレームおよび引数の情報は、新しい ICorProfilerInfo3 メソッドが呼び出されたときに限定的に初期化されます。
ELT3 インターフェイスは、旧バージョンの .NET Framework の ELT インターフェイス (ELT1 および ELT2) と互換性があります。
.NET Framework 4 では、ELT3 上に ELT2 関数を実装しており、追加のハッシュ テーブルを使用してクライアント ID と関数 ID を対応付けます。 そのため、ELT2 関数を使用すると、同期による負荷が大きくなり、プロファイリングの速度が低下します。 高い負荷がかかっているマルチプロセッサ コンピューターでは、パフォーマンスはさらに低下します。ただし、プロファイラーを ELT3 API に移行するために必要なコード変更は簡単で負担も少ないので、最高のパフォーマンスを得るには、ELT3 を採用することをお勧めします。
ELT3 の関数とメソッド
ELT3 API には、次の 3 種類のメンバーが用意されています。
通知関数。対象アプリケーションの関数に制御が渡されていることをプロファイラーに通知するために、CLR によって呼び出されます。
登録メソッド。高速パスまたは低速パスの検査メソッドを有効にするために、プロファイラーによって呼び出されます。
検査メソッド。引数または戻り値の情報を取得するために、プロファイラーによって呼び出されます。
ELT3 通知関数
.NET Framework 4 以降では、6 つの ELT3 通知関数のうち 3 つを使用して、対象アプリケーション (プロファイリングされているアプリケーション) の関数に制御が渡されていることをプロファイラーに通知できます。 ELT3 通知関数は、高速パス関数と低速パス関数で構成されます。
高速パス関数の特性は、JIT コンパイル コードにおいて、中間コードなしにプロファイラーの ELT メソッドを直接呼び出すことです。
低速パス関数の特性は、JIT コンパイル コードにおいて、中間コード (通常は、CLR DLL にコンパイルされるアセンブリ コードと C コードの組み合わせ) を呼び出してから、最終的にプロファイラーの ELT メソッドを呼び出すことです。
次の 3 つの関数は高速パス関数で、必要なパラメーターは 1 つだけです。パラメーターは、制御が渡される、または返される対象となる関数の ID、または tail 呼び出しを実行しようとしている関数の ID です。
次の 3 つの関数は低速パス関数で、必要なパラメーターは 2 つです。パラメーターは、関数 ID と、スタック フレームに関する情報へのハンドルです。
これらの 3 つの関数では、ランタイムからプロファイラーに渡される 2 番目のパラメーター (eltInfo) は、スタックに割り当てられる _COR_PRF_ELT_INFO_INTERNAL 構造体への非透過なポインターです。 この構造体には、ELT アセンブリ ヘルパーによって生成されるプラットフォーム固有のハンドルが含まれます。 プロファイラーでは、ICorProfilerInfo3::GetFunctionEnter3Info、ICorProfilerInfo3::GetFunctionLeave3Info、および ICorProfilerInfo3::GetFunctionTailcall3Info の各メソッドで eltInfo ポインターを使用できます。
ELT3 登録メソッド
次の 2 つの ELT3 登録メソッドを使用して、低速パス ELT 関数と高速パス ELT 関数を設定できます。
アプリケーションの起動時、これらのメソッドのどちらかをプロファイラーの ICorProfilerCallback::Initialize コールバックまたは ICorProfilerCallback3::InitializeForAttach コールバックから呼び出す必要があります。 プロファイラーでは、SetEventMask を使用して目的のイベント フラグを登録する必要があります。その後、高速パス ELT3 を有効にするには SetEnterLeaveFunctionHooks3 メソッド、低速パス ELT3 を有効にするには SetEnterLeaveFunctionHooks3WithInfo メソッドを呼び出します。
高速パス ELT3 フックは低速パス ELT3 フックと共には使用できず、ELT3 フックは ELT1 フックまたは ELT2 フックと共には使用できません。 SetEnterLeaveFunctionHooks3 または SetEnterLeaveFunctionHooks3WithInfo を呼び出す前に、低速パスを必要とする適切なイベント フラグ (COR_PRF_ENABLE_FUNCTION_ARGS、COR_PRF_ENABLE_FUNCTION_RETVAL、または COR_PRF_ENABLE_FRAME_INFO) をプロファイラーで指定していない場合、エラーを示す CORPROF_E_INCONSISTENT_WITH_FLAGS エラー コードが返されます。
ELT3 検査メソッド
ELT3 通知関数では引数または戻り値の情報は提供されません。そのため、プロファイラーでは、次の ICorProfilerInfo3 検査メソッドのいずれかを呼び出して、目的の情報を明示的に要求する必要があります。
これらのメソッドは、対応する低速パス ELT3 関数 (FunctionEnter3WithInfo、FunctionLeave3WithInfo、および FunctionTailcall3WithInfo) のプロファイラーの実装から呼び出す必要があり、プロファイラーでは、ELT 通知関数から受け取ったものと同じ eltInfo 値を指定する必要があります。 ELT3 検査メソッドは、ELT3 高速パス通知関数 (FunctionEnter3、FunctionLeave3、FunctionTailcall3) のプロファイラーの実装からも、ELT1 通知関数または ELT2 通知関数のいずれからも、呼び出すことができない点に注意してください。