首页 > 代码库 > 通过编译的方式,思考如何让程序更快(原创)

通过编译的方式,思考如何让程序更快(原创)

在.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,eax11 000007fe`942600a2 7405            je      000007fe`942600a912 000007fe`942600a4 e85363a45f      call    clr!JIT_DbgIsJustMyCode (000007fe`f3ca63fc)13 000007fe`942600a9 90              nop14 15 D:\Study\ConsoleApp\Program.cs @ 20:16 000007fe`942600aa b901000000      mov     ecx,117 000007fe`942600af e874bfeeff      call    000007fe`9414c028 (ConsoleApp.Program.Add(Int32), mdToken: 0000000006000002)18 000007fe`942600b4 90              nop19 20 D:\Study\ConsoleApp\Program.cs @ 21:21 000007fe`942600b5 66ba2b00        mov     dx,2Bh22 000007fe`942600b9 b901000000      mov     ecx,123 000007fe`942600be e86dbfeeff      call    000007fe`9414c030 (ConsoleApp.Program.Calc(Int32, Char), mdToken: 0000000006000003)24 000007fe`942600c3 90              nop25 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.dll29 000007fe`942600ca e8b1d2d256      call    mscorlib_ni+0xd0d380 (000007fe`eaf8d380) (System.Console.WriteLine(Int32), mdToken: 0000000006000990)30 000007fe`942600cf 90              nop31 32 D:\Study\ConsoleApp\Program.cs @ 23:33 000007fe`942600d0 eb00            jmp     000007fe`942600d234 000007fe`942600d2 90              nop35 000007fe`942600d3 4883c428        add     rsp,28h36 000007fe`942600d7 c3              ret
View Code

用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,2Bh12 000007fe`9426009e b901000000      mov     ecx,113 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.dll18 000007fe`942600ae e8cdd2d256      call    mscorlib_ni+0xd0d380 (000007fe`eaf8d380) (System.Console.WriteLine(Int32), mdToken: 0000000006000990)19 000007fe`942600b3 90              nop20 000007fe`942600b4 4883c428        add     rsp,28h21 000007fe`942600b8 c3              ret
View Code

 

可以看出:

大小:Debug版本size 48,Release版本size 29

19行:Debug版本有进入Main方法的代码块的额外操作(待研究)

20行:Debug版本有调用Add方法的开销,Release版本内联处理而直接inc计算

21行:由于Calc方法包含异常处理模块,所以无法内联,Debug版本和Release版本都有调用的开销

22行:都有调用系统方法WriteLine的开销

23行:Debug版本有离开Main方法的代码块的额外操作

 

实际上,JIT使用大量的探测方法来确定是否应内联某个方法,虽然不必刻意使所写的方法满足内联的条件,但合理使用有助于让程序更快。

通过编译的方式,思考如何让程序更快(原创)