JIT Compilation Module Overview
Total Page:16
File Type:pdf, Size:1020Kb
JIT Compilation Module Overview JIT Compilation Native vs. Managed Compilation Managed Execution Phases Assembly Loading & Initialization JIT Compilation JIT Optimizations What’s new in NGEN 4.0? When to use NGEN? 2 Running Code Behavior in Windows 2000 - Legacy entry point mscoree!CorExeMain gets used Behavior in Windows XP - The operating system loader checks for managed modules by examining a bit in the common object file format (COFF) header - The bit being set denotes a managed module - If the loader detects managed modules, it loads mscoree.dll, and clr!CorValidateImage and clr!CorImageUnloading notify the loader when the managed module images are loaded and unloaded clr!CorValidateImage performs the following: - Ensures that the code is valid managed code - Changes the entry point in the image to an entry point in the runtime On 64-bit Windows, _CorValidateImage modifies the image that is in memory by transforming it from PE32 to PE32+ 3 Native compile vs Managed compile Simplified view of native code compilation Native Code .CPP or .C file .OBJ File (Machine .EXE or .DLL File containing C or C++ Compile Link language) (Machine language) code d T e y i s p T n c e y fo r p r ib e m in d a g e ti s o c n r ib in g in fo rm a tio n 4 Native compile vs Managed compile Simplified view of managed code compilation Managed Code Machine Language Assembly(.EXE or .CS File containing C# generated in memory Compile .DLL) containing MSIL Execute code at runtime by JIT and Metadata compiler 5 Managed Execution Phases Phase .NET Source code Compile Time CompileIL and Metadata IL and Metadata Run Time JITNative (CLR) Code Native Code 6 JIT Compilation What does JIT do? Checks if function is called 1st time - JIT compiles IL code to native code if true Stores native code in memory Updates MethodDescriptor field - Reference updated to point to memory location of native code 7 Managed Execution JIT Compilation MyModule::Main No First call? Retrieve address of native Yes code from MethodDesc CILJit::compileMethod (x86) PreJit::compileMethod (x64) [verifies and compiles the IL] Execute the native code Native code, GCInfo, EH data,etc. Store native code in memory Store the address in MethodDesc 8 MethodDescriptor Contains implementation of a managed method Generated as part of the class loading procedure Initially points to IL Code Can be determined during debugging - !SOS.DumpMD <MethodDesc address> 0:004> !dumpmd 009969a8 Method Name: MyApp.MainForm.menu_Click(System.Object, System.EventArgs) Class: 00cd5c0c MethodTable: 00996ad4 mdToken: 0600028d Module: 00992c3c IsJitted: no CodeAddr: ffffffff Transparency: Critical 9 Managed Execution Assembly Loading and Initialization MSCoreEE.dll is loaded Process starts and loads the .NET Process Main thread starts executing Framework by calling _CorExeMain Initializes CLR ClassLoader is called Reads MetaData tables Execute Main Build InMemory representation JIT compile the Main method MethodTable & EEClass 10 Anatomy of a managed non-value instance (very schematic) Loader Heap EEClass MethodTable GC Heap Full (“Cold”) Instance EEClass* metadata “Hot” metadata MethodTable* Method MethodDesc Desc* Pointer to VTables •PreJittedStub Field layout •JItted code •“IL” stub * == Pointer 11 !DumpClass & DumpMT 12 JIT Optimizations Summary Types of Optimization: - JIT Inlining - JIT Tail Calls 13 JIT Optimizations Tail Calls When the last thing a function does is call another function - Calls without Optimization: static public void Main() Call One() { Call Two() Helper(); Call Three() } - With Optimization: static public void Helper() { Call One() One(); Call Two() Two(); Jump Three() Three(); - will use the same stack space as the caller. } - improve data locality, memory usage, static public void Three() and cache usage. { ... } 14 JIT Optimizations Tail Calls Tail Call Feature set different between X86 and X64 - Can lead to e.g. Stack Overflow Exception on X86 Debug but works fine on X64 ( where x86 stack just enough in release with tail call, but overflows without optimization) No Tail Calls possible if: - Caller doesn't return immediately after the call - Stack arguments between caller and callee are incompatible in a way that would require shifting things around in the caller's frame before the callee could execute - Caller and callee return different types - We inline the call instead (inlining is way better than tail calling, and opens the door to many more optimizations) - Security issues - The debugger / profiler turned off JIT optimizations - Full list see: .NET 2.0 Tail limits and .NET 4.0 Tail Limits 15 JIT Optimizations – Inlining class Test { Without inlining static int And(int i1, int i2) { return i1 & i2; } static int i; static public void Main() { i = And(i, 0); } } With inlining class Test { static int i; static public void Main() { i = 0 // xor edx,edx } } 16 JIT Optimizations – Inlining Main() Without Inlining: <Setup stack> mov ecx,dword ptr ds:[183368h] ; setup first argument (i) xor edx,edx ; setup second argument (0) call dword ptr ds:[183818h] (Inline.Program+Test.And(Int32, Int32), mdToken: 06000002) ; Call And(…) mov dword ptr [ebp-4],eax ; save return value mov eax,dword ptr [ebp-4] ; assign result to static mov dword ptr ds:[00283368h],eax ; assign result to static <cleanup stack> ret ; return And(Int32, Int32) <Setup stack> mov eax,dword ptr [ebp-4] ; move arg 1 to eax and eax,dword ptr [ebp-8] ; Add argument 2 to eax (return register) <cleanup stack> ret ; return to caller 17 JIT Optimizations – Inlining With Inlining - And(.,.) is inlined now - No add reg,reg - because not needed (argument is 0) MethodDesc Table Entry MethodDesc JIT Name 53dda7e0 53bb4934 PreJIT System.Object.ToString() 53dde2e0 53bb493c PreJIT System.Object.Equals(System.Object) 53dde1f0 53bb495c PreJIT System.Object.GetHashCode() 53e61600 53bb4970 PreJIT System.Object.Finalize() 001dc019 001d3828 NONE Inline.Program+Test..ctor() 001dc011 001d3810 NONE Inline.Program+Test.And(Int32, Int32) 00270070 001d381c JIT Inline.Program+Test.Main() Main() xor edx,edx ; generate final result mov dword ptr ds:[1D3368h],edx ; move result to static ret ; return 18 Demo: JIT Compilation !dumpmt –md bp cmdStartJit_Click JIT Optimizations Additional Config Instruct CLR not to optimize the code (during jit) without recompiling the dll: - Use an ini file (and symbols) • MyDll.ini: [.NET Framework Debugging Control] GenerateTrackingInfo=1 (per default on up from .NET 2.0) AllowOptimize=0 • (useable for GAC as well) Instruct CLR to ignore (optimized) Ngen Image - Use Environment variable: set COMPLUS_ZapDisable=1 20 JIT Performance Counters - % Time in Jit % elapsed time in JIT compilation since JIT started Updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled. A value > 5% can indicate a problem - Is Ngen an option? • http://msdn.microsoft.com/en-us/magazine/cc163610.aspx - Do you use multiple AppDomains? • loading assemblies as domain neutral can help - Minimize the classes and assemblies within code path • Use code coverage to determine these components. - See .NET Framework Usage Performance Rules/DA0009 21 JIT Performance Counters -summary Performance counter Description Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by # of IL Bytes the just-in-time (JIT) compiler since the application started. This counter is equivalent to JITted the Total # of IL Bytes Jitted counter. # of IL Methods Displays the total number of methods JIT-compiled since the application started. This JITted counter does not include pre-JIT-compiled methods. Displays the percentage of elapsed time spent in JIT compilation since the last JIT % Time in Jit compilation phase. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled. Displays the number of MSIL bytes that are JIT-compiled per second. This counter is IL Bytes Jitted / not an average over time; it displays the difference between the values observed in the sec last two samples divided by the duration of the sample interval. Displays the peak number of methods the JIT compiler has failed to compile since the Standard Jit application started. This failure can occur if the MSIL cannot be verified or if there is an Failures internal error in the JIT compiler. Total # of IL Displays the total MSIL bytes JIT-compiled since the application started. This counter is Bytes Jitted equivalent to the # of IL Bytes Jitted counter. 22 JIT Performance Counters - % Time in Jit % elapsed time in JIT compilation since JIT started Updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled. A value > 5% can indicate a problem - Is Ngen an option? • http://msdn.microsoft.com/en-us/magazine/cc163610.aspx - Do you use multiple AppDomains? • loading assemblies as domain neutral can help - Minimize the classes and assemblies within code path • Use code coverage to determine these components. - See .NET Framework Usage Performance Rules/DA0009 23 JIT Performance Counters -summary Performance counter Description Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by # of IL Bytes the just-in-time (JIT) compiler since the application started. This counter is equivalent to JITted the Total # of IL Bytes Jitted counter. # of IL Methods Displays the total number of methods JIT-compiled since the application started. This JITted counter does not include pre-JIT-compiled methods. Displays the percentage of elapsed time spent in JIT compilation since the last JIT % Time in Jit compilation phase. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled. Displays the number of MSIL bytes that are JIT-compiled per second. This counter is IL Bytes Jitted / not an average over time; it displays the difference between the values observed in the sec last two samples divided by the duration of the sample interval.