游戏开发论坛

 找回密码
 立即注册
搜索
查看: 26770|回复: 22

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

[复制链接]

20

主题

451

帖子

470

积分

中级会员

Rank: 3Rank: 3

积分
470
发表于 2007-11-16 04:05:00 | 显示全部楼层 |阅读模式
这是我自己翻译的一篇文章,由于本人英语有限,所以其中会有翻译错误或者不准确的地方,建议英文好的朋友看原文。
原文:
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:ength来代替额外的长度参数
    * 涉及到三角函数的地方都改为使用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一窍不通!

89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
发表于 2007-11-16 09:51:00 | 显示全部楼层

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

任何一个告诉你托管代码比非托管代码慢的人,都是没有考虑到.NET运行机制的人,简单的说,就是对.NET一窍不通!

89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
发表于 2007-11-16 10:20:00 | 显示全部楼层

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

你说的很对,但是不要过于激动,打倒一种极端不能走向另外一种极端。比较这个没有太多的意义。即使是VB6也不是纯解释性的代码,java也早已改进。

考虑一种语言和编译器的产生的程序的运行效率有4个方面:

1、编译器翻译代码的效率,你只谈到了IL的翻译效率,其实C++/C包括其他很多编译器都可以对自己的代码翻译成机器语言的过程进行优化,C++/C甚至可以直接嵌入汇编来达到优化,请问.NET可以吗?.NET的优化是MS一厢情愿的,在不同的应用场合,有时候反而适得其反。

2、编译器翻译动态代码的大小。运行时间和静态代码的大小虽然没有什么直接联系,但是如果运行时代码的语句过多,效率会下降很多,举个很典型的例子,.NET的数组遍历,每次遍历都会检查数组越界,虽说每次检查执行的指令只有1-2个,但是这也是牺牲效率为代价的。如果我们熟悉面向对象的设计理念,就会发现.NET的对象粒度比较大,所谓粒度很大就是说你每干一件事就要做许多额外的工作,这些额外的工作有时候是我们所需要的,但有些时候却是多余的。如果粒度太小,我们开发起来的效率就会下降,这2者总是会有一点顾此失彼的。


下面2点就不用我说了吧。
3、开发人员的编码习惯。

4、机器的执行效率。

一切从实际出发。达到我们的需求就好。

14

主题

345

帖子

376

积分

中级会员

Rank: 3Rank: 3

积分
376
QQ
发表于 2007-11-16 14:15:00 | 显示全部楼层

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

仅凭一个算法看不出优势来的
原来还过JAVA也这样证明自己效率快的

20

主题

451

帖子

470

积分

中级会员

Rank: 3Rank: 3

积分
470
 楼主| 发表于 2007-11-16 17:38:00 | 显示全部楼层

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

呵呵,都说了上面那篇文章只是翻译国外的一篇文章~
我翻译过来只是想说明,并不是是.net写的程序就一定比c++慢,而且就算是某些方面慢,也不是因为中间代码IL的原因,很多人误以为IL也是一种解译语言。很多时候更重要的是程序员代码的质量问题。(有一点我必须承认,.net的WinForm类确实很慢,跟c++用MFC比起来,但这不代表.net什么东西都比c++慢,如果觉得Winform不够快,一样可以自己重新写窗体类)

的确里面谈到的问题很局限,没有谈到.NET复杂的GC系统(其实也可以算是一个最拖.net运行速度的玩意儿)。但是另外一方面来看,.net的代码确实很安全,特别是大型工程,不会花太多功夫来检查内存泄露之类的问题。还有你说的边界检查问题,的确会消耗额外的资源,不过,在某些时候这种检查是非常必要的!我现在开发的是网络游戏服务器端的模拟器,试想如果没有边界检查,一个黑客找到了弄崩溃你服务器的方法,然后往内存写入攻击代码,服务器的安全就不保了!当然c++也可以做到防止这种事情发生,不过,你所投入的精力会非常多!

这里一段题外话:
这里不是为了要说c++比c#差,只是说不能用工具的不同来断定程序的运行速度。举个例子
ManGOs,WoW的模拟器,用c++写的,在线人数到60人就会卡的不行。我现在参加的一个项目,同样也是网游的模拟器(C#写的,复杂程度不比WoW低,由于这游戏国内还没出,所以名字不说了),我们团队是从去年11月开始开发的(也就是说也有一年的开发时间了)。最近开放了一个公开测试服务器,在线人数最多达到过150人,一点都不会卡(刷的怪物有大约5000个),CPU负载,3个程序总共5%左右。
这也就说明了,程序执行效率受工具的影响远远小于受程序架构以及代码质量的影响(其实Mangos慢的主要原因是他使用单线程处理,如果我们那模拟器也用单线程处理,大约也只能支持50-60人,就会开始很卡)

.net还有一个c++所无法办到的就是跨平台,虽然现在不是所有平台都支持.net,不过是事实是,只要是装了wince的PDA,或者是XBOX,或者是Linux。都可以将windows下编译的.exe文件,不经任何处理直接运行与其他平台(我们的模拟器在Linux下运行非常完美,没有为支持Linux多写一行代码!)

还有内嵌汇编的事情,是谁给你说的.net不能内嵌汇编呢?
给你看下面一段代码,是我现在开发的项目里面的一段:
obj = helper
                    .ldc_i4(paracount)
                    .newarr(typeof(object))
                    .stloc_0;
                    for (int i = 0; i < paracount; i++)
                    {
                        int j;
                        if (isstatic) j = i; else j = i + 1;
                        switch (j)
                        {
                            case 0:
                                obj = helper
                                .ldloc_0
                                .ldc_i4_0
                                .ldarg_0;
                                break;
                            case 1:
                                obj = helper
                                .ldloc_0
                                .ldc_i4_1
                                .ldarg_1;
                                break;
                            case 2:
                                obj = helper
                                .ldloc_0
                                .ldc_i4_2
                                .ldarg_2;
                                break;
                            case 3:
                                obj = helper
                                .ldloc_0
                                .ldc_i4_3
                                .ldarg_3;
                                break;
                            default:
                                obj = helper.ldnull;
                                break;
                        }
                        if (isstatic)
                            obj = helper
                            .box(paras[j].ParameterType);
                        else
                            obj = helper
                            .box(method.myType.myType.UnderlyingSystemType);
                        obj = helper
                        .stelem_ref;                                
                    }
别告诉我.ldc_i4这些IL汇编语句不是汇编!
虽然不能非常方便的这样内嵌80386汇编,但是并不是不可能!

103

主题

1432

帖子

1458

积分

金牌会员

Rank: 6Rank: 6

积分
1458
QQ
发表于 2007-11-16 19:49:00 | 显示全部楼层

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

java 其实也和.net一样快的,架构类似,速度优化方面会在一个水平。

及时是同样的编译型语言,速度差别在一个数量级也是有可能的。因此我觉得这种虚拟机语言已经做得比较好。
只是有一点不能认同,就是垃圾收集;如果能像c++那样,比较准确的释放资源(不止是内存),那样可能更加适合吧。



89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
发表于 2007-11-19 09:56:00 | 显示全部楼层

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

别告诉我.ldc_i4这些IL汇编语句不是汇编!


哈哈

0

主题

3

帖子

8

积分

新手上路

Rank: 1

积分
8
发表于 2007-11-21 00:46:00 | 显示全部楼层

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

文章不错,我确实有把C#当成JAVA一起鄙视的心理习惯,虽然心里知道C#运行机制和JAVA好像很不一样..
   LZ的道理说的不错...嘎嘎..   
    事实上我对C#本来就没有什么抵触心理,一直觉得很不错,类库超级方便(有时候甚至用盗版VS2005,都有种惭愧的感觉,因为.NET这个东西MS做的超级BIG,超级费心,而我一分钱不出,就拿过来用了.^_^ 中国这么多盗版的,盖茨要气晕了,哈哈)

34

主题

629

帖子

629

积分

高级会员

Rank: 4

积分
629
发表于 2007-11-21 11:05:00 | 显示全部楼层

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

c++的优势不仅仅是效率
LZ可知道这十几年来全世界一共积累了多少c++的代码
又有几个游戏是推翻一切从头写起的?
如果只是想写个小Demo,那无所谓,否则,除非微软先用c#开发几十个顶级游戏并将他们开源,否则做游戏还是要用c++

20

主题

451

帖子

470

积分

中级会员

Rank: 3Rank: 3

积分
470
 楼主| 发表于 2007-11-23 03:03:00 | 显示全部楼层

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

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

c++的优势不仅仅是效率
LZ可知道这十几年来全世界一共积累了多少c++的代码
又有几个游戏是推翻一切从头写...

这位大哥说的才是正解~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 09:34

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表