更新 : 2007 年 11 月
これまでのトピックでは、アプリケーションとプロファイラの実行中に何が起こるのかについて説明しました。では、この 2 つはアプリケーションの起動時にどのように接続されるのでしょうか。共通言語ランタイム (CLR: Common Language Runtime) は、各プロセスの初期化時に接続を行います。CLR はプロファイラに接続するかどうかを決定します。接続することに決めた場合は、2 つの環境変数の値を次の順番で調べて、プロファイラを探します。
COR_ENABLE_PROFILING: この環境変数が存在し、1 に設定されている場合にのみ、CLR はプロファイラに接続します。
COR_PROFILER: COR_ENABLE_PROFILING のチェックに合格した場合、CLR はこの CLSID または ProgID (あらかじめレジストリに格納されている) を持つプロファイラに接続します。COR_PROFILER 環境変数は文字列として定義されます。以下に 2 つの例を示します。
set COR_PROFILER={32E2F4DA-1BEA-47ea-88F9-C5DAF691C94A} set COR_PROFILER="MyProfiler"
したがって、CLR アプリケーションのプロファイリングを行うには、COR_ENABLE_PROFILING 環境変数および COR_PROFILER 環境変数を設定してから、アプリケーションを実行する必要があります。さらに、プロファイラ DLL が登録済みであることを確認してください。
環境変数名のスコープ
COR_ENABLE_PROFILING 環境変数と COR_PROFILER 環境変数をどのように設定するかによって、これらの変数が影響を及ぼすスコープが決定します。これらの変数は、次のいずれかの方法で設定できます。
ICorDebug::CreateProcess 呼び出し内で設定した変数は、その時点で実行しているアプリケーションにのみ適用されます (そのアプリケーションから起動されて環境を継承する他のアプリケーションにも適用されます)。
コマンド プロンプト ウィンドウで設定した変数は、そのウィンドウから起動したすべてのアプリケーションに適用されます。
ユーザー レベルで設定した変数は、Windows エクスプローラを使用して起動するすべてのアプリケーションに適用されます。変数を設定した後にコマンド プロンプト ウィンドウを開くと、それらの環境設定が表示されます。そのウィンドウから起動するアプリケーションにも同じ設定が適用されます。ユーザー レベルで環境変数を設定するには、[マイ コンピュータ] を右クリックし、[プロパティ] をクリックします。[詳細設定] タブをクリックし、[環境変数] をクリックして、[ユーザー環境変数] の一覧に変数を追加します。
コンピュータ レベルで設定した変数は、そのコンピュータで起動するすべてのアプリケーションに適用されます。そのコンピュータでコマンド プロンプト ウィンドウを開くと、それらの環境設定が表示されます。そのウィンドウから起動するアプリケーションにも同じ設定が適用されます。つまり、そのコンピュータ上のすべてのマネージ プロセスがプロファイラと共に起動します。コンピュータ レベルで環境変数を設定するには、[マイ コンピュータ] を右クリックし、[プロパティ] をクリックします。[詳細設定] タブをクリックし、[環境変数] をクリックします。[システム環境変数] の一覧に変数を追加し、コンピュータを再起動します。再起動後、変数はシステム全体で試用できるようになります。
Windows サービスのプロファイリングを行う場合は、環境変数を設定した後、コンピュータを再起動してプロファイラ DLL を登録する必要があります。これらの考慮事項の詳細については、「Windows サービスのプロファイリング」を参照してください。
その他の考慮事項
プロファイラ クラスは ICorProfilerCallback インターフェイスと ICorProfilerCallback2 インターフェイスを実装します。.NET Framework Version 2.0 では、プロファイラは ICorProfilerCallback2 を実装する必要があります。実装していない場合、ICorProfilerCallback2 は読み込まれません。
一度に 1 つのプロファイラのみが、指定された環境でプロセスのプロファイリングを行うことができます。2 つの異なるプロファイラを別々の環境に登録することはできますが、各プロファイラは別々のプロセスのプロファイリングを行う必要があります。プロファイラは、インプロセス COM サーバー DLL として実装する必要があります。この DLL は、プロファイリング対象プロセスと同じアドレス領域にアップされます。つまり、プロファイラはインプロセスで実行されます。.NET Framework では、これ以外の種類の COM サーバーはサポートしていません。たとえば、プロファイラがリモート コンピュータからアプリケーションを監視する場合は、各コンピュータにコレクタ エージェントを実装する必要があります。実装したエージェントは、結果をまとめて中央のデータ収集用コンピュータに送信します。
プロファイラはインプロセスでインスタンス化される COM オブジェクトであるため、プロファイリングされる各アプリケーションに専用のプロファイラのコピーが存在します。したがって、単一のプロファイラ インスタンスが複数のアプリケーションからのデータを処理する必要はありません。ただし、プロファイラのログ コードに、他のプロファイリング対象アプリケーションからのログ ファイルの上書きを回避するロジックを追加する必要があります。
プロファイラの初期化
両方の環境変数のチェックに合格すると、CLR は COM CoCreateInstance 関数と同様の方法でプロファイルのインスタンスを作成します。このプロファイルについては、CoCreateInstance の直接呼び出しによる読み込みは行われません。そのため、スレッド処理モデルの設定が必要な CoInitialize の呼び出しが回避されます。CLR は、次にプロファイラ内で ICorProfilerCallback::Initialize メソッドを呼び出します。このメソッドのシグネチャは次のとおりです。
HRESULT Initialize(IUnknown *pICorProfilerInfoUnk)
プロファイラは、pICorProfilerInfoUnk に ICorProfilerInfo インターフェイス ポインタまたは ICorProfilerInfo2 インターフェイス ポインタを照会して保存し、後でプロファイリングを行うときに詳細情報を要求できるようにします。
イベント通知の設定
プロファイラは、次に ICorProfilerInfo::SetEventMask メソッドを呼び出して、確認する通知のカテゴリを指定します。たとえば、関数の Enter および Leave の通知とガベージ コレクションの通知のみを確認する場合は、次のように指定します。
ICorProfilerInfo* pInfo;
pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo, (void**)&pInfo);
pInfo->SetEventMask(COR_PRF_MONITOR_ENTERLEAVE | COR_PRF_MONITOR_GC)
通知マスクをこのように設定することによって、プロファイラで受け取る通知を制限できます。この方法は、単純なプロファイラまたは特別な目的を持つプロファイラを作成するときに役立ちます。また、プロファイラが無視するだけの通知を送信するのに消費される CPU 時間が削減されます。
特定のプロファイラ イベントは変更できません。つまり、これらのイベントが ICorProfilerCallback::Initialize コールバックで設定されるとすぐに、イベントはオフにできなくなり、新しいイベントをオンにすることもできません。変更できないイベントを変更しようとすると、失敗を表す HRESULT が ICorProfilerInfo::SetEventMask から返されます。