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

在.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

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

《Java程序性能优化:让你的Java程序更快、更稳定》

Java程序性能优化:让你的Java程序更快.更稳定, 卓越网更便宜,不错的书吧

如何让程序更快的运行

1.客观上说程序运行必会收到硬件资源如CPU计算能力.IO读写速度.网络带宽和软件资源如sockets连接数.数据库连接数的限制,为了更快的让程序运行尽早完成它要完成的任务就要突破这些限制.突破硬件资源的限制的方法是将程序的任务分解到多台硬件组成的集群上来执行:突破软件资源的限制可通过资源池的方式来解决. 2.为了更快的提升计算资源的使用效率,电脑系统中运行最快的CPU采用时间片轮换的方式来执行多个任务,如果一个任务还没执行完就要保存当前任务的上下文,下次再执行时再加载这个任务的上下文,这个过程

笔记《Java程序性能优化 让你的Java程序更快、更稳定》 第二章 设计调优

2.1 善用设计模式 23 (1) 1. 设计模式好处: 2.1.1 单例模式 23 (6) 1. 单例模式是一种对象创建模式,用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例: 2. 两大好处:a.对于频繁创建的对象,可以省略创建对象所花费的时间:b.new操作减少,因而对系统内存的使用频率也会降低,降低GC压力,缩短GC停顿时间: 3. 单例模式的参与者:单例类和使用者: 4. 第一种实现方式:私有默认构造器,静态getInstance方法:这种实现方式简单.可靠,但不能延迟

反编译Android APK及防止APK程序被反编译

原文出处 反编译Android APK及防止APK程序被反编译 怎么逆向工程对Android Apk 进行反编译 google Android开发是开源的,开发过程中有些时候会遇到一些功能,自己不知道该怎么做,然而别的软件里面已经有了,这个时候可以采用反编译的方式,解开其他的程序,来了解一些它 的做法,同时啊,还可以借鉴别人的软件结构,资源文件:作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用的APK进行反编译查看.此方式主要目的是为了促进开发者学习,借鉴好的代

Atitit.hybrid混合型应用 浏览器插件,控件的实现方式 浏览器运行本地程序的解决方案大的总结---提升用户体验and开发效率..

Atitit.hybrid混合型应用 浏览器插件,控件的实现方式 浏览器运行本地程序的解决方案大的总结---提升用户体验and开发效率.. 1. hybrid App 1 1.1. Hybrid App为什么会兴起编辑 1 1.2. 如何实现网页语言与程序语言的混合编辑 2 1.2.1. 多View混合型 2 1.2.2. 单View混合型 2 1.2.3. Web主体型 2 1.3. Hybrid App的瓶颈与未来编辑 3 2. Web App.Hybrid App.Native APP对比

在Mac OS X上用自己编译出的CoreCLR运行.NET程序

当昨天被Mac OS X上无法编译CoreCLR的问题困扰时(详见Mac OS X上尝试编译CoreCLR源代码),后来发现这个难题竟然被神人@kangaroo给解决了,连CoreCLR的微软开发人员也大吃一惊(详见#105). @kangaroo This is awesome! Thank you so much for doing it! I’ll start reviewing it in the morning. 今天发现,@kangaroo修改后可在OS X上编译的版本已被合并到Co

在SoCEDS环境下编译和更新preloader和uboot程序的方法

在SoCEDS环境下编译和更新preloader和uboot程序的方法 前面有介绍preloader在HPS boot过程中的的作用,接下来讲述下用户在SoCEDS环境下改如何编译preloader和uboot程序!以及如何去更新BOOT SD卡中的preloader和uboot! 从Terasic网站下下载的SD image是在13.1环境下编译出来的preloader和u-boot,这里会在14.0环境下重新编译并更新到SD卡中!并在inux系统下更新preloader和u-boot到SD卡

编译Ngnix遇到的问题,查看程序依赖的库文件

要点:ldd 可以读取每个可以运行的程序依赖的 so 文件. 编译的时候提示需要Openssl库. 查看本机,已经安装了openssl 查看编译报错文件,查找Openssl所依赖的库 more objs/autoconf.err 查看openssl所依赖的库文件 ldd /usr/bin/openssl ldd –u /usr/bin/openssl objdump -x obj 以某种分类信息的形式把目标文件的数据组织(被分为几大块)输出 objdump -t obj 输出目标文件的符号表 o

使用命令行编译打包运行自己的MapReduce程序 Hadoop2.6.0

使用命令行编译打包运行自己的MapReduce程序 Hadoop2.6.0 网上的 MapReduce WordCount 教程对于如何编译 WordCount.java 几乎是一笔带过… 而有写到的,大多又是 0.20 等旧版本版本的做法,即 javac -classpath /usr/local/hadoop/hadoop-1.0.1/hadoop-core-1.0.1.jar WordCount.java,但较新的 2.X 版本中,已经没有 hadoop-core*.jar 这个文件,因此