.Net的程序运行效率比VC++低?不!翻译自国外的一篇文章

 这是我自己翻译的一篇文章,由于本人英语有限,所以其中会有翻译错误或者不准确的地方,建议英文好的朋友看原文。
原文:
http://www.grimes.demon.co.uk/dotnet/man_unman.htm

托管代码(.net)比非托管代码(vc++)慢吗?

如果你用上面这个问题去问每一个人,基本上每个人都会回答,肯定会慢! 那么他们说的是正确的吗? 不,并不正确。 问题在于,绝大多数人认为.Net只是一个基于运行库的框架,就像Java或者VB,或者他们甚至以为.Net使用像Java一样的虚拟机系统。 他们并沒考虑到程序本身,沒考虑到程序是用来干什么,也没有考虑到访问网络或者磁盘的速度因素。简单来说,就是他们根本没有思考!

.NET并不像那种运行库(VB或者Java)。 它是一个经过精心构思的,并且微软在其身上下了极大功夫的框架,以保证它的良好运行。 在这篇文章 我将给大家展示一些将需要大量运算的代码,并且将他编译成托管以及非托管代码。 然后我将测量这两个库分别的表现。 你将看到, 并不会因为这是.net程序就自动要比c++程序慢,事实是,在某些情况,托管代码甚至比非托管代码更快。

题外话(我自己补充的,原文没有提到):
.NET的运行机制,由于本人现在研究的项目跟.Net库底层有些关系,所以多少了解一些,现在简单给大家介绍一下。
基本上每个人都知道的是,所有.Net语言都将被编译成为一个叫做IL汇编的中间语言。但是计算机是如何执行这个中间代码的,却是很多人不知道,甚至理解错误了的。
JIT是.NET程序运行的重要部件之一,全称是即时编译器。我刚才说的误解,就是很多人(绝对不是少数,问了很多c++程序员,10个有9个这种想法)都以为JIT其实就是跟Java VM差不多的东西,是一个Interpreter,在运行时读取IL汇编代码,然后模拟成x86代码(也就是俗称的虚拟机)。但是事实上,.NET使用的是更为高级的技术。 .Net程序被加载入内存以后,当某段IL代码被第一次运行的时候,JIT编译器就会将这段IL代码,全部编译成本地代码,然后再执行。这也就是为什么.NET程序第一次运行都启动很慢的原因! 随.NET库,微软还附带了一个工具,可以事先将.NET程序所有的IL代码都编译成本地代码并保存在缓存区中,这样一来,这个程序就跟c++编译的一模一样了,没有任何区别,运行时也可以脱离JIT了(这里不要混淆了,这里不是说可以脱离.NET库,而是说不需要在进行即时编译这个过程了)。所以,请不要将.NET和Java混为一谈,两个的运行效率根本不是一个等级的!

作为测试算法,我们选中了FFT(Fast Fourier Transform),这是一个将跟时间有关系的数据(例如音乐)转换成他应有的频率信息的算法。
这个算法有很多种,如果你用Google搜索会发现很多,这里我选中了Real Discrete Fourier Transform, 因为他比较简单明了,比较好修改。 我将其复制了4份,分别用于测试托管的C++, C++/CLI,C#。

非托管的代码我只是将其函数名称改成了fourier,并且加入了__declspec(dllexport)用来导出。
托管的代码改动的要稍多些:

    * 方法参数改成了托管的Array, 并且使用Array::Length来代替额外的长度参数
    * 涉及到三角函数的地方都改为使用Math类下的方法
    * 算法被作为一个公开类的静态成员导出

然后我把托管的c++代码转换成了c#,只做了极小的变化(大多数是语法上以及申明上的改动)
最后,我又将托管的c++代码转换成了C++/CLI

然后我们将所有版本都分别编译几个不同的版本:未优化版,空间优化,速度优化.

结果:
我将这些程序分别在两台电脑上进行了测试,一台是装了.net 2.0的 XPSP2,处理器是PIII 850, 512MB内存。 另外一台是Vista build 5321,处理器是2GHz 移动PIV,1G内存,每次测试我都是取100次算法运算的平均值,结果单位是毫秒,以下是PIII电脑的运行结果:
            沒优化   进行了空间优化  进行了速度优化
Unmanaged  92.88 ± 0.09  88.23 ± 0.09  68.48 ± 0.03
Managed C++  72.89 ± 0.03  72.26 ± 0.04  71.35 ± 0.06
C++/CLI  73.00 ± 0.05  72.32 ± 0.03  71.44 ± 0.04
C# Managed  72.21 ± 0.04  69.97 ± 0.08

PIV电脑的结果:
            沒优化   进行了空间优化  进行了速度优化
Unmanaged  45.2 ± 0.1  30.04 ± 0.04  23.06 ± 0.04
Managed C++  23.5 ± 0.1  23.17 ± 0.08  23.36 ± 0.07
C++/CLI  23.5 ± 0.1  23.11 ± 0.07  23.80 ± 0.05
C# Managed  23.7 ± 0.1  22.78 ± 0.03

可以看出,非托管代码在不同的优化方案上存在很大的效率差异,PIII上不优化比优化慢35%,在PIV上也是。 在这个简陋的统计上表明,不管是哪种优化方案,管理代码在运行效率上并没有太大区别,编译器和连接器并没有影响到运行效率太多, 我在后面会说更多关于这方面的信息。
奇怪的是,在Vista下,管理代码进行空间优化甚至比进行速度优化速度更快!

C#的结果跟托管的C++比起来,并没有太大区别,但是可以看到, 优化过的c#代码比优化过的托管C++代码要稍快些

现在来比较以下托管代码和非托管代码的结果。 在不优化的情况下,托管代码远远快于非托管代码,这个差距在优化空间后被稍微缩短了点,只有在进行速度优化后,非托管代码才比托管代码稍稍快上一点
非托管代码和C#代码的差别只有3%左右,不过,c#代码仍然比c++的更快! 

.NET的编译器(在这个情况下是托管的C++代码) 可以看成是与非托管C++编译器的Parser引擎是等价的。编译器将生成类,方法等的表,然后进行了一系列的高等级优化。 .NET真正的非托管编译器其实是JIT(即时编译器):这才是程序真正转换成低等級的x86代码的地方..NET编译器和JIT编译的组合,其实跟非托管C++编译器等价的,唯一的不同是,.Net被分成了两个部分.事实上,JIT在运行托管代码时,对.NET程序针对客户电脑进行了优化,而不是像非托管代码那样是在程序员电脑上进行的优化。结果表明,托管C++代码和c#代码的优化设置带来的影响非常小。 显而易见的是,C#代码至少是跟C++代码同样高效。

记住! 在.NET中没有任何一个部分是自动就必C++代码慢的,运行效率完全取决于程序员。任何一个告诉你托管代码比非托管代码慢的人,都是没有考虑到.NET运行机制的人,简单的说,就是对.NET一窍不通!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值