在之前另一篇回复中,已经提出来,firelong的逻辑有欠严谨。这是因为firelong所说的linq似乎是指linq2sql,而linq2sql并非C#的一种特性。如今firelong又提出C#性能不能承受之慢,这一篇文章在我看来,存在更多的逻辑漏洞。很可惜的是,有许多人在回复中的评论,并没有正确的指出这一点。
首先,我这里需要提出一个问题是:C#性能慢,是与什么做比较?是与C、C++比较呢,还是与Java或者Php?或者还是说比光速慢?使用“慢”这种形容词的时候,必定是需要和特定东西做比较的。我想,几乎不需要思考,都可以肯定一点——C#不会比我写的一个什么语言解释器要慢。既然firelong并没有提出,C#比什么慢,那么诸位直接提出反对意见,就等于跳到了一个永远不可能逃出来的圈套中。
如果需要反驳,那么最简单的一个办法就是,替firelong在这方面做出一些个特定的假设,比如说,C#的性能比C慢,又或者C#的性能比java慢,再或者C#的性能比PHP慢。这么反驳即便不能一下子成功,也至少可以迫使firelong在这一个最基本的问题上做出澄清,比如说:我firelong说的是C#的性能比汇编慢,又或者,我firelong说的是C#的性能总之就是慢。前者我们可以得到一个清晰的辩论平台,后者我们就可以清楚看到firelong词穷。在firelong做出实际解释之前,我们也可以针对假设做一些有意思的研究。
假如说firelong指的是C#比C或者C++慢,我想,在同等的算法前提下,这应该是毋庸置疑的。一种是使用VM的,另一种是直接执行的,在算法到机器指令的转换上面,实际上是不可能直接完全等价的。比如说,C编译出来的程序考虑了数组下标超界问题吗? 或者在比如C会提供GC吗?假如,我们把C程序写成具备这些C#直接支持的功能上面,那么其结果可能会拉近一大步。然而,实际上一般的比较都不是这么进行的,而是直接用类似的源代码所编译出来的程序来比较,这本身已经是不公平的了。那么,即便忽略掉这些基本的差别不谈,我们会发现这样的比较有什么问题呢?
第一,这样的比较逻辑不严谨,这并非C#造成的,而是.NET的架构本身所导致的。难道VB.NET就快了,F#就快了。不是的,他们都同样的受着类似问题的煎熬。
第二,这样的比较基本上没有什么意义,这是因为C(包括C++)和C#的应用场景是完全不一样的。比如说,如果用C#开发操作系统内核,它可以吗?显然不行,这是尤其.NET平台自身的局限性所导致的。那么用C来开发一个Web前端,可行吗?可以,但几乎不可行,因为这实在不是C的强项,如果用C描述Web上面的元素会比较麻烦。既然两个应用场景不相同的语言,拿到一起来比较,那根本就没有意义。这就好比说C的可维护性远不及C#一样,又好比Java比C慢。
第三,即便忽略上述两点,我们还会发现这样的逻辑证明有一个巨大的缺陷——无法解释现实发生的情况。比如说,结构实现几乎完全相同,并且面向目标完全相同的java,为什么从2001年至今,几乎一直占据着开发语言中的头把交椅呢? 因为java比C慢吗?既然比C慢对于java的发展不是一个问题,那么如何证明这对C#就会成为一个问题了?
具体参考: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
又假如说firelong指的是C#比java慢,那么我觉得这样的比较还具备一定的意义,因为这两种平台的应用场景重叠的地方还真不是一星半点。那么事实上,C#比java慢吗?这个事实就留待大家自己去研究吧,总体而言,在性能方面,实际上应当是.NET平台比Java平台优秀。别的不说,光说装箱拆箱,说泛型这两件事情,从理论上说,就应当如此。当然了,这是在双方的具体算法一致,或者至少是近似的前提下,才能得出这样的结论的。我们抛开启动速度不说,光说具体指令性能,我找了一个很老的研究结果(04年的,估计现在.NET平台在性能上,应该会有一些变化): http://www.osnews.com/story/5602/Nine_Language_Performance_Round-up_Benchmarking_Math_File_I_O/page3/
int math |
long math |
double math |
trig |
I/O |
TOTAL |
|
Visual C++ | 9.6 | 18.8 | 6.4 | 3.5 | 10.5 | 48.8 |
Visual C# | 9.7 | 23.9 | 17.7 | 4.1 | 9.9 | 65.3 |
gcc C | 9.8 | 28.8 | 9.5 | 14.9 | 10.0 | 73.0 |
Visual Basic | 9.8 | 23.7 | 17.7 | 4.1 | 30.7 | 85.9 |
Visual J# | 9.6 | 23.9 | 17.5 | 4.2 | 35.1 | 90.4 |
Java 1.3.1 | 14.5 | 29.6 | 19.0 | 22.1 | 12.3 | 97.6 |
Java 1.4.2 | 9.3 | 20.2 | 6.5 | 57.1 | 10.1 | 103.1 |
Python/Psyco | 29.7 | 615.4 | 100.4 | 13.1 | 10.5 | 769.1 |
Python | 322.4 | 891.9 | 405.7 | 47.1 | 11.9 | 1679.0 |
上表是具体的执行时间,单位为秒,自然是越小越好。那么结果如何呢?至少不是三言两语就能得出一个这样的结论:C#比XXXX慢。嗯,你可以说,这个肯定是哪一个MS的托,否则C#怎么可能在某些性能上比GCC还快?这个我也姑且持保留意见,问题是,咱们别空对空,给出具体的数据,比如说另一个网站的数据是怎么说的。又或者说,你做了一个什么样的实验,结果如何。我自己是没有什么兴趣做这样的实验,因为个人觉得这根本不是个什么问题。
再来假设,firelong说的是C#的性能比PHP慢。这样的话呢,也至少还有一点可比性,因为他们在Web前端开发中都是其应用场景。(如果我硬要拿PHP做客户端来和C#比较快慢,那肯定是哪里不正常了。)为什么我会提firelong做这么一个假设呢?因为firelong提出来说,排名前多少的站点没有一个是用asp.net的,其中举了一个facebook的例子。facebook如果没有搞错,应该主要是使用php的吧?嗯,先不管是不是,从另一个角度讲,php在网站开发的占有量上面,估计是C#的2倍甚至可能更多。参考http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html这里的说法,PHP近9%,而C#略超5%,而且C#还有不少的开发是做客户端的。那么PHP是因为比C#快,所以才有这么多网站,尤其是著名网站选择使用吗?我们再来看另一个数据:
http://naspinski.net/post/AspNet-vs-php--speed-comparison.aspx
谁快谁慢,咱们一目了然了吧?
在这里,我们不得不说一下统计学的一个问题:要得到因果关系是非常困难的,尤其是谁是因,谁是果。如果我们没有取得有关C#与另一种语言X的速度比较数据,也没有具体统计使用C#和X的站点数量等,就匆忙下结论:C#比X用的少的原因,是因为C#比X慢,这是很不负责任的。更何况,这样选择统计,是否正确还是一个问题。是使用C#还是X,有很多不受控的变量,比如说,个人喜好,商业政治,学习成本等,还有很多也许有可能受控的变量,比如开发成本、部署成本、性能等。仅仅从这么少的数据,试图找出其中一个变量“性能”和结果之间的“相关性”,恐怕是非常值得怀疑的。即便是非得要这么考虑问题,我们至少应该看趋势,而不是现状。如果我们考察趋势,那么我们更难解释C#慢(到让人无法忍受)这个结论。因为C#的市场占有率是上升的,而不是下降的。(很奇怪吧,java却是下降的,如果firelong说这是因为java慢,我可能还少一个可以辩驳的理由。)
另外,别的不说,招行个人银行用的是asp.net,这点不用质疑吧。那么,招行慢了吗?登陆你就无法忍受了,交易过程慢的也无法忍受了?用很多顶尖平台不使用“.NET平台进行开发”的例子,来证明其慢,是不充分的。除非你做出深入的分析,比如说,影响其决策的因素有哪些,各自所占的权重如何(拿数据说明为什么),否则,你除了能证明他们不用.NET平台之外,证明不了什么问题。
另外,再次说明,C#比某些语言速度慢,不是C#造成的,而是平台造成的。比如说,如果你写一个编译器,把他直接编译成不带任何检查,不带GC的机器码,速度就能立即达到C的近似水平。如果你再继续使用unsafe指针,那就更没有差别了。正是这些firelong所喜欢的东西,造成了其性能的最大问题。那些所谓的linq,语法糖等等,即便有性能损失,也和前面提到的性能损失不在一个数量级之上,这一点是极具讽刺意味的。而事实上,某些firelong所不喜欢的东西,却提高了性能。比如说:
http://blog.zhaojie.me/2009/08/from-delegate-to-others-3.html
如果没有时间仔细研究,那就看这个具体的结论吧:
Normal
Time Elapsed: 3,127ms
CPU Cycles: 6,362,621,144
Gen 0: 624
Gen 1: 3
Gen 2: 0
Fast
Time Elapsed: 2,031ms
CPU Cycles: 4,070,470,778
Gen 0: 312
Gen 1: 0
Gen 2: 0
Lambda
Time Elapsed: 2,675ms
CPU Cycles: 5,672,592,948
Gen 0: 312
Gen 1: 156
Gen 2: 0
上面的Normal是我们使用传统方式编写代码,Fast是使用“循环合并”这种带有“臭味”的不良开发模式编写出来的代码,而Lambda就不用多说了吧。firelong在反对这些提高性能的东西前提下,指责C#因此变慢,这个逻辑我是没有想明白的。也许firelong需要对此多下些功夫进行解释了。
另外,我也呼吁大家,拿事实说话,因为我们要讨论的是事实而不是人品。如果拿不出来,那么最好是旁观不语。骂大街的方式其实没有什么意义,除了能彰显你的人品低下。