c# - ICorProfilerCallback2: CLR profiler does not log all Leave calls -


i trying write profiler logs .net method calls in process. goal make highly performant , keep let's last 5-10 minutes in memory (fixed buffer, cyclically overwrite old info) until user triggers info written disk. intended use track down reproducing performance issues.

i started off simpleclrprofiler project https://github.com/appneta/simpleclrprofiler. profiler makes use of icorprofilercallback2 callback interface of .net profiling. got compile , work in environment (win 8.1, .net 4.5, vs2012). however, noticed leave calls missing enter calls logged. example of console.writeline call (i reduced output of dbgview minimally necessary understand):

line 1481: entering system.console.writeline line 1483: entering synctextwriter.writeline line 1485: entering system.io.textwriter.writeline line 1537: leaving synctextwriter.writeline 

two entering calls don't have corresponding leaving calls. profiled .net code looks this:

console.writeline("hello, simple profiler!"); 

the relevant simpleclrprofiler methods are:

hresult csimpleprofiler::registerglobalcallbacks()  {    hresult hr = profilerinfo3->setenterleavefunctionhooks3withinfo(       (functionenter3withinfo*)methodentered3,        (functionenter3withinfo*)methodleft3,        (functionenter3withinfo*)methodtailcall3);     if (failed(hr))       trace_f(l"failed 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 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 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()); } 

does have idea, why .net profiler not perform leave calls leaving methods? way, checked onleavemethod not unexpectedly exit before trace due exception or so. doesn't.

thanks, christoph

since stakx not seem coming question provide official answer (and credit) him: stakx had hinted at, didn't log tail calls. in fact, wasn't aware of concept had ignored hook method (it wired empty). found explanation of tail calls here: http://blogs.msdn.com/b/davbr/archive/2007/06/20/enter-leave-tailcall-hooks-part-2-tall-tales-of-tail-calls.aspx

i quote link above:

tail calling compiler optimization saves execution of instructions , saves reads , writes of stack memory. when last thing function call function (and other conditions favorable), compiler may consider implementing call tail call, instead of regular call.

consider code:

static public void main() {     helper(); }  static public void helper() {     one();     three(); }  static public void three() {     ... } 

when method three called, without tail call optimization, stack this.

three helper main 

with tail call optimization, stack looks this:

three main 

so before calling three, due optimization, method helper popped of stack , result, there 1 less method on stack (less memory usage) , executions , memory write operations saved.


Comments

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -