Just-in-time (JIT) optimizations are defined in the DebuggableAttribute custom attribute. When compiled in debug mode, this attribute is added to the metadata of the application with any optimizations disabled. The DebuggableAttribute attribute contains the IsJITOptimizerDisabled and IsJITTrackingEnabled properties, which indicate the status of JIT optimizations.
These optimizations can make debugging a production application difficult. Fortunately, you can create an application initialization file that disables the optimization of a release product. The initialization file must be in the same directory as the application, have the same root name of the application, and have the .ini extension. For myapp.exe, the filename would be myapp.ini. The initialization file has two entries. The GenerateTrackingInfo entry enables or disables generating complete tracking information. This entry is redundant in .NET 2.0, where tracking information is always generated. The AllowOptimize entry controls code optimization. In the initialization file, 1 is true and 0 is false. The following is an initialization file that disables both JIT optimizations:
[.NET Framework Debugging Control] GenerateTrackingInfo=1 AllowOptimize=0
This is a partial listing of assembly code generated by the JIT compiler with optimizations enabled:
00e40a0b 8b45b8 mov eax,[ebp-0x48] 00e40a0e 8b8854010000 mov ecx,[eax+0x154] 00e40a14 8b15086c3902 mov edx,[02396c08] ("Transaction cancelled") 00e40a1a 8b01 mov eax,[ecx] 00e40a1c ff9068010000 call dword ptr [eax+0x168] 00e40a22 83c301 add ebx,0x1 00e40a25 3b5ddc cmp ebx,[ebp-0x24] 00e40a28 0f8c58fdffff jl 00e40786 00e40a2e 8d65f4 lea esp,[ebp-0xc] 00e40a31 5b pop ebx 00e40a32 5e pop esi 00e40a33 5f pop edi 00e40a34 5d pop ebp 00e40a35 c20400 ret 0x4 00e40a38 e8713f2579 call mscorwks!JIT_RngChkFail (7a0949ae) 00e40a3d cc int 3
The following assembly originated from the same Microsoft intermediate language (MSIL) code as the preceding assembly code. For this assembly, the JIT optimizations are disabled. I will not torment you with the intricacies of assembly code. However, compare the before and after code—and note the differences. Obviously, disabling optimizations made a considerable difference in the assembly code generated.
01050aba 90 nop 01050abb eb17 jmp 01050ad4 01050abd 8b45c0 mov eax,[ebp-0x40] 01050ac0 8b8854010000 mov ecx,[eax+0x154] 01050ac6 8b15086c3902 mov edx,[02396c08] ("Transaction cancelled") 01050acc 8b01 mov eax,[ecx] 01050ace ff9068010000 call dword ptr [eax+0x168] 01050ad4 ff45d4 inc dword ptr [ebp-0x2c] 01050ad7 8b45d4 mov eax,[ebp-0x2c] 01050ada 3b45d8 cmp eax,[ebp-0x28] 01050add 0f8c1efdffff jl 01050801 01050ae3 90 nop 01050ae4 8d65f4 lea esp,[ebp-0xc] 01050ae7 5b pop ebx 01050ae8 5e pop esi 01050ae9 5f pop edi 01050aea 5d pop ebp 01050aeb c20400 ret 0x4
Other differences can exist between release and debug products. Debug methods are likely to be omitted from the release version. Trace methods are probably included in the release build, but that is not guaranteed. These and other dissimilarities sometimes amount to relevant differences between a release and debug version of a product. For that reason, an abnormal condition in a production application may mysteriously disappear in a debug version. The opposite also applies. Errors in a debug version might disappear in the release product. Make sure that Debug and Trace methods cause no side effects. This will eliminate most cross-build problems. It's important to always extensively test both the debug and release versions of products. After exhaustive unit testing of the debug build, submit the release build to identical tests.