Profiling with the ELT API
Tracing profilers log function enters and exits, and can also maintain historical call graphs. To help implement this functionality, the .NET Framework provides the profiling global static functions, which contain sets of related functions and interfaces known as the enter/leave/tailcall (ELT) APIs.
Before the .NET Framework 4, tracing profilers that used ELT functions paid a performance cost that increased as the number of small managed functions increased. Starting with the .NET Framework 4, you can use the ELT version 3 (ELT3) API for ELT performance improvements, particularly when there is no need for argument or return value inspection. Performance improvements include the following:
The size of just-in-time compiled code decreases for ELT fast-path functions.
The number of required ELT arguments is reduced to a minimum, which decreases stack space requirements for parameters that are passed to the profiler.
Stack frame setup and argument inspection occur only when they are needed, which increases execution speed.
Frame and argument information are lazily initialized when a new ICorProfilerInfo3 method is called.
ELT3 interfaces are compatible with the ELT interfaces (ELT1 and ELT2) in earlier versions of the .NET Framework.
The .NET Framework 4 implements ELT2 functions on top of ELT3 and uses an extra hash table to map between client IDs and function IDs. This results in significant synchronization cost and slow profiling when using the ELT2 functions. Performance degradation is even worse on heavily loaded multiprocessor computers. However, the code changes that are required to migrate a profiler to ELT3 APIs are straightforward and low-cost, so we recommend that you adopt ELT3 for the best performance.
The ELT3 API provides three types of members:
Notification functions, which are called by the CLR to notify a profiler that control is being passed to a function in the target application.
Registration methods, which are called by the profiler to enable either fast-path or slow-path inspection methods.
Inspection methods, which are called by the profiler to retrieve argument or return value information.
Starting with the .NET Framework 4, you can use three out of six ELT3 notification functions to notify the profiler that control is being passed to a function in the target application (the application being profiled). The ELT3 notification functions consist of fast-path functions and slow-path functions:
Fast-path functions are characterized by JIT-compiled code that calls directly into the profiler’s ELT methods without any intermediary code.
Slow-path functions are characterized by JIT-compiled code that calls into an intermediary (usually a combination of assembly code and C code that is compiled into the CLR DLL) before eventually calling into the profiler’s ELT methods.
The following three functions are fast-path functions and require only one parameter, the identifier of the function to which control is being passed or returned, or that is about to make a tail call:
The following three functions are slow-path functions and require two parameters, the function identifier and a handle to information about a stack frame:
In these three functions, the second parameter (eltInfo) that the runtime passes to the profiler is an opaque pointer to a _COR_PRF_ELT_INFO_INTERNAL structure that is allocated on the stack. This structure encloses the platform-specific handle that is generated by the ELT assembly helpers. The profiler can use the eltInfo pointer in the ICorProfilerInfo3::GetFunctionEnter3Info, ICorProfilerInfo3::GetFunctionLeave3Info, and ICorProfilerInfo3::GetFunctionTailcall3Info methods.
You can use the following two ELT3 registration methods to set slow-path and fast-path ELT functions:
One of these methods must be called when the application starts, from the profiler’s ICorProfilerCallback::Initialize or ICorProfilerCallback3::InitializeForAttach callback. The profiler has to register the desired event flag with SetEventMask before it calls either the SetEnterLeaveFunctionHooks3 method to enable fast-path ELT3 or the SetEnterLeaveFunctionHooks3WithInfo method to enable slow-path ELT3.
Fast-path ELT3 hooks cannot be mixed with slow-path ELT3 hooks, and ELT3 hooks cannot be used with ELT1 or ELT2 hooks. If the profiler has not specified appropriate event flags that require a slow path (COR_PRF_ENABLE_FUNCTION_ARGS, COR_PRF_ENABLE_FUNCTION_RETVAL, or COR_PRF_ENABLE_FRAME_INFO) before calling into SetEnterLeaveFunctionHooks3 or SetEnterLeaveFunctionHooks3WithInfo, the CORPROF_E_INCONSISTENT_WITH_FLAGS error code is returned to indicate the failure.
ELT3 notification functions do not provide argument or return value information; therefore, the profiler must explicitly request the information it wants by calling one of the following ICorProfilerInfo3 inspection methods:
These methods must be called from the profiler’s implementation of the corresponding slow-path ELT3 function (FunctionEnter3WithInfo, FunctionLeave3WithInfo, and FunctionTailcall3WithInfo), and the profiler has to provide the same eltInfo value that it received from the ELT notification function. Note that the ELT3 inspection methods may not be called from the profiler’s implementation of an ELT3 fast-path notification function (FunctionEnter3, FunctionLeave3 , FunctionTailcall3), or from any ELT1 or ELT2 notification function.