プロセス内のすべての .Net メソッド呼び出しをログに記録するプロファイラーを作成しようとしています。目標は、パフォーマンスを高め、ユーザーがその情報をディスクに書き込むようにトリガーするまで、最後の 5 ~ 10 分間をメモリ (固定バッファー、周期的に古い情報を上書きする) に保持することです。使用目的は、めったに再現されないパフォーマンスの問題を追跡することです。
https://github.com/appneta/SimpleCLRProfilerの SimpleCLRProfiler プロジェクトから始めました。プロファイラーは、.Net プロファイリングのICorProfilerCallback2コールバック インターフェイスを利用します。私の環境(Win 8.1、.Net 4.5、VS2012)でコンパイルして動作させることができました。ただし、Enter コールがログに記録されているのに、Leave コールが欠落している場合があることに気付きました。Console.WriteLine 呼び出しの例 (DbgView の出力を、理解するために最低限必要なものに減らしました):
Line 1481: Entering System.Console.WriteLine
Line 1483: Entering SyncTextWriter.WriteLine
Line 1485: Entering System.IO.TextWriter.WriteLine
Line 1537: Leaving SyncTextWriter.WriteLine
2 つの Entering 呼び出しには、対応する Leaveing 呼び出しがありません。プロファイリングされた .Net コードは次のようになります。
Console.WriteLine("Hello, Simple Profiler!");
関連する SimpleCLRProfiler メソッドは次のとおりです。
HRESULT CSimpleProfiler::registerGlobalCallbacks()
{
HRESULT hr = profilerInfo3->SetEnterLeaveFunctionHooks3WithInfo(
(FunctionEnter3WithInfo*)MethodEntered3,
(FunctionEnter3WithInfo*)MethodLeft3,
(FunctionEnter3WithInfo*)MethodTailcall3);
if (FAILED(hr))
Trace_f(L"Failed to register global callbacks (%s)", _com_error(hr).ErrorMessage());
return S_OK;
}
void CSimpleProfiler::OnEnterWithInfo(FunctionID functionId, COR_PRF_ELT_INFO eltInfo)
{
MethodInfo info;
HRESULT hr = info.Create(profilerInfo3, functionId);
if (FAILED(hr))
Trace_f(L"Enter() failed to create MethodInfo object (%s)", _com_error(hr).ErrorMessage());
Trace_f(L"[%p] [%d] Entering %s.%s", functionId, GetCurrentThreadId(), info.className.c_str(), info.methodName.c_str());
}
void CSimpleProfiler::OnLeaveWithInfo(FunctionID functionId, COR_PRF_ELT_INFO eltInfo)
{
MethodInfo info;
HRESULT hr = info.Create(profilerInfo3, functionId);
if (FAILED(hr))
Trace_f(L"Enter() failed to create MethodInfo object (%s)", _com_error(hr).ErrorMessage());
Trace_f(L"[%p] [%d] Leaving %s.%s", functionId, GetCurrentThreadId(), info.className.c_str(), info.methodName.c_str());
}
.Net プロファイラーがすべての終了メソッドに対して Leave 呼び出しを実行しない理由を知っている人はいますか? ちなみに、OnLeaveMethod が例外などでトレース前に予期せず終了しないことを確認しました。そうではありません。
ありがとう、クリストフ