在.NET程序第一阶段编译时,有两种方式:
Debug版本主要便于调试分析。
Release版本进行了各种优化,体积更小、执行更快、编译更慢更严格。
体积更小,主要是因为Release版本中去掉了程序中所有的断点、代码行等调试信息。
那么执行更快究竟为什么呢?
一段简单的测试代码(原创帖,转载请说明出处)
用WinDbg分析Debug版本
1 Normal JIT generated code 2 ConsoleApp.Program.Main() 3 Begin 000007fe94260090, size 48 4 *** WARNING: Unable to verify checksum for ConsoleApp.exe 5 6 D:\Study\ConsoleApp\Program.cs @ 19: 7 >>> 000007fe`94260090 4883ec28 sub rsp,28h 8 000007fe`94260094 48b848341494fe070000 mov rax,7FE94143448h 9 000007fe`9426009e 8b00 mov eax,dword ptr [rax] 10 000007fe`942600a0 85c0 test eax,eax 11 000007fe`942600a2 7405 je 000007fe`942600a9 12 000007fe`942600a4 e85363a45f call clr!JIT_DbgIsJustMyCode (000007fe`f3ca63fc) 13 000007fe`942600a9 90 nop 14 15 D:\Study\ConsoleApp\Program.cs @ 20: 16 000007fe`942600aa b901000000 mov ecx,1 17 000007fe`942600af e874bfeeff call 000007fe`9414c028 (ConsoleApp.Program.Add(Int32), mdToken: 0000000006000002) 18 000007fe`942600b4 90 nop 19 20 D:\Study\ConsoleApp\Program.cs @ 21: 21 000007fe`942600b5 66ba2b00 mov dx,2Bh 22 000007fe`942600b9 b901000000 mov ecx,1 23 000007fe`942600be e86dbfeeff call 000007fe`9414c030 (ConsoleApp.Program.Calc(Int32, Char), mdToken: 0000000006000003) 24 000007fe`942600c3 90 nop 25 26 D:\Study\ConsoleApp\Program.cs @ 22: 27 000007fe`942600c4 8b0d7a35eeff mov ecx,dword ptr [000007fe`94143644] 28 *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\abf62e6545d2802fc60286678a67e6bf\mscorlib.ni.dll 29 000007fe`942600ca e8b1d2d256 call mscorlib_ni+0xd0d380 (000007fe`eaf8d380) (System.Console.WriteLine(Int32), mdToken: 0000000006000990) 30 000007fe`942600cf 90 nop 31 32 D:\Study\ConsoleApp\Program.cs @ 23: 33 000007fe`942600d0 eb00 jmp 000007fe`942600d2 34 000007fe`942600d2 90 nop 35 000007fe`942600d3 4883c428 add rsp,28h 36 000007fe`942600d7 c3 ret
用WinDbg分析Release版本
1 Normal JIT generated code 2 ConsoleApp.Program.Main() 3 Begin 000007fe94260090, size 29 4 *** WARNING: Unable to verify checksum for ConsoleApp.exe 5 6 D:\Study\ConsoleApp\Program.cs @ 20: 7 >>> 000007fe`94260090 4883ec28 sub rsp,28h 8 000007fe`94260094 ff05aa35eeff inc dword ptr [000007fe`94143644] 9 10 D:\Study\ConsoleApp\Program.cs @ 21: 11 000007fe`9426009a 66ba2b00 mov dx,2Bh 12 000007fe`9426009e b901000000 mov ecx,1 13 000007fe`942600a3 e888bfeeff call 000007fe`9414c030 (ConsoleApp.Program.Calc(Int32, Char), mdToken: 0000000006000003) 14 15 D:\Study\ConsoleApp\Program.cs @ 22: 16 000007fe`942600a8 8b0d9635eeff mov ecx,dword ptr [000007fe`94143644] 17 *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib\abf62e6545d2802fc60286678a67e6bf\mscorlib.ni.dll 18 000007fe`942600ae e8cdd2d256 call mscorlib_ni+0xd0d380 (000007fe`eaf8d380) (System.Console.WriteLine(Int32), mdToken: 0000000006000990) 19 000007fe`942600b3 90 nop 20 000007fe`942600b4 4883c428 add rsp,28h 21 000007fe`942600b8 c3 ret
可以看出:
大小:Debug版本size 48,Release版本size 29
19行:Debug版本有进入Main方法的代码块的额外操作(待研究)
20行:Debug版本有调用Add方法的开销,Release版本内联处理而直接inc计算
21行:由于Calc方法包含异常处理模块,所以无法内联,Debug版本和Release版本都有调用的开销
22行:都有调用系统方法WriteLine的开销
23行:Debug版本有离开Main方法的代码块的额外操作
实际上,JIT使用大量的探测方法来确定是否应内联某个方法,虽然不必刻意使所写的方法满足内联的条件,但合理使用有助于让程序更快。
时间: 2024-10-14 06:06:51