zl程序教程

您现在的位置是:首页 >  其他

当前栏目

C#确实是很“慢”——最后的疯狂

2023-04-18 15:17:03 时间

说真的,我也开始觉得大家认为“firelong是dudu请来的公关”这种理论是有道理的。因为这位英雄一开贴就炸出一个大坑,众多博客园中的老一辈已经出现了很多。这不,我宣布了无限期潜水都跳出来了,搬出去的Jeffrey也在这里面不停的回复。哈哈,知道我还看到了谁?装配脑袋哦!嗯,不知道接着灵感之源是否会出现。这真像是一个大狂欢啊!(怀念过去博客园那种讨论气氛。)


不过我也确实感觉到:这会不会是博客园历史发展上的一个重要事件呢?比如说,这是老一批博主聚得最齐的一次聚会,或者以后我们会发现博客园的娱乐化开始是以这一个事件作为其起始标志的呢?例如,这几篇文章被标注为“C#语言之争”话题,多少有点误导观众,甚至是起到一种娱乐化的效果。

 

言归正传,C#确实是“慢”(假如跟C/C++比的话),我从来没有否认。不过我过去会、现在会、将来还是会纠正那么一把:那是.NET Framework及其底层机制慢。firelong其实已经自己证明了这一点,他说,MetaData是慢的一个重要原因。MetaData本来就不是C#语言本身必须的一个特征,否则firelong也不会提出要把这个该死的东西给删掉。firelong你又何必一边强调“我们谈C#,就是在谈.NET Framework”,一边又在谈其实和C#没有关系的东西呢?你这让装配脑袋这些实用VB.NET的兄弟们情何以堪啊!要知道,使用VB.NET的人,也不算在少数。其实,我们可以大大方方的谈论.NET Framework的性能瓶颈,而没有必要非要拉上C#陪葬,对吧?(嗯,后面会稍微呼应一下。) 

 

重要提示:我真的从来没有说过C#比什么都快,或者.NET Framework不存在可以提升性能的地方,也没有说过.NET或者C#不存在累赘或者不合理的设计。我之前回firelong的文章,不是说firelong说的是错的,或者不是事实,而是说他的论述过程不严谨,甚至语言词汇使用的也不严谨。firelong说的是对的,或者他说的是一个事实,自然也不是你应该从此得到的结论。请大家在我的帖子里面评论的时候少说“嗯,C#就是快,xxx是叛徒。”或者“C#就是慢,楼主你还好意思不承认,青鸟出来的吧”。如果这样,你至少犯了三个错误:

1、你压根没仔细读懂我的文章,或者明知不该为而为之,因为我已经劝你别这么做了;

2、你跑题了, 我这里确实不打算讨论这个问题;

3、你使用的字眼给你自己贴了一个很不好的标签。

 

[慢] 

再次给所有使用、或者打算使用C#的,同时看到此文的人认真体会我这句强调了无数遍的话:.NET Framework及其底层机制,决定了你开发出来的程序比使用完全相同算法的C/C++开发出来的程序,无论是大小还是速度上,都不会占到什么便宜。在开始选型之前,要小心谨慎的衡量这一点。比如说:其内存占用会多出来大约5MB到20MB不等,因为.NET Framework一次会加载整个类库,不能够说你想要拿一个方法、函数或者类,就只在最终编译出来的可执行文件中仅包含他们(你不能选择静态连接),当然你也不能够选择不要Meta(一般如果是ASP.NET,保守估计,可能会占你100MB,不过有人也做实验了http://www.cnblogs.com/Ivony/archive/2010/06/24/1764677.html,说Meta不会一次全都加载进去。我没仔细看,大家可以看看)。高性能密集运算时间综合看,其运行所需时间大约是其2-3倍。当然,这是一个很复杂的问题,比如循环相加int没有什么差别,但别的可能差10倍以上也不一定,上述2到3倍是一般正常的“综合油况”。

 

打一个补丁有人说,你那个2-3倍空口无凭,是一种臆测。嗯,我确实需要承认,我当时没有把我为什么这么说的依据明确的写出来。不过如果认真看过firelong文章C#会重蹈覆辙吗?反射及元数据的性能问题的同学,应该也会看到另外有人写了一个帖子:

C# vs C++ 全局照明渲染性能比试

这里面我们姑且认为是一个较为完整的程序,而且还是CPU密集型的。而我的原话说“高性能密集运算时间综合看,其运行所需时间大约是其2-3倍”的结论,主要是根据这里面得到的一个结果,而且我也说了大约,毕竟只是一个小测试。后面说,“当然,这是一个很复杂的问题,比如循环相加int没有什么差别”,这个我在之前的回firelong之C#慢里面已经提到过了。后面我接着说,“但别的可能差10倍以上也不一定”,大家注意,我说的时可能,万事皆有可能嘛。好,如果还是觉得我说的一点根据也没有,我也承认这里我之前是没有给出例子的,我这里就给补上:
http://shootout.alioth.debian.org/u64/performance.php?test=fasta

  倍数 程序源代码CPU时间(秒)使用时间(秒)
0.1C++ GNU g++ #50.210.22
1.0GNU gcc #31.631.62
5.2C# Mono #28.478.47

注意C#(Mono)实现所需要的时间,是C++ GNU g++ #5 的多少倍呢?看不到的我给摘录一下:当然,哪一个是经过特别改造的版本,算法并非完全相同。不过大家应该很容易理解我想说的意思吧?再者,我还是只能很无奈的强调,我并不像讨论C#有多快还是有多慢,我想说的是,咱们讨论的时候,稍微严谨一点,给点数据,然后别扣帽子,别乱跑题就好了。


顺便也说一下,如果我哪一句话让你觉得我人身攻击了,又或者哪一句话缺乏证据了,请告诉我,我会尽快修正,不会跑题的。我绝不是那种宽于律己,严于律人的那种人。 

 

另外也顺便看看java和C#的对比:

http://shootout.alioth.debian.org/u32q/csharp.php

我觉得这里面的数据还挺值得稍微看一下的。 

  

[YY一把]

当然了,如果你已经恋上C#了,想听一点好听的,那我也可以说一点(谁要YY也请不要算到我的头上)。相对C++来说,你可以在以下方面得到以下好处:

1)托管平台比非托管平台,在出现指针错误的几率上,小很多;

2)托管平台比非托管平台,在出现内存泄露的几率上,小很多;

3)托管平台比非托管平台,在出现缓冲区溢出的几率,小很多; 

4).NET Framework的某些技术(依赖于Meta),使得你可以避免一些Dll地狱的问题;

5)C#在语义表达上,更有效率,或者说:同样一个任务,可以用更少的行数来表达。

(当然还有很多啦,YY嫌疑的话题,还是少谈为妙,这不是我想要表达的重点。重点是:互有利弊。我为啥这么啰嗦呢?没办法,我不想再看到评论中出现这样类型的讨论,我既没多大兴趣讨论这些问题,又不希望别人误导大众,很矛盾啊,会精神分裂的。)

 

上述说的,其实是开发效率和成本的问题。这里面解释一下第5点:如果我没有记错的话,这么多年来的研究发现,每人年代码行数几乎是一个常数,比如用汇编的时候是1200行每人每年,用C的时候是1500,用C++的时候是1400,java是1800,C#是1600(注意比如二字)。嗯,你可以说我这是没有证据的,没错,我必须承认我没有列出来,可能需要以后补一下。不过好像人月神化上就有吧?假设上述正确,我们可以推测一个成因:人的理解能力及沟通能力是有限的。可是同样是大概1200行代码,C#如果能做4个任务而C++能做1个,那么是否效率就高了呢?应该是吧!(我很想用显然,不过还是严谨一点好。)Brooks在人月神化中说,根据数据推测,使用高级语言比使用汇编,效率提高了5倍。至于C#比C++提高多少倍,我就不知道了。

 

在上面着一个分析下面,还隐藏着一些很有意思的问题。比如说,为什么我们感觉.NET圈子里面的人似乎平均素质比较低呢?为什么我们感觉.NET写出来的程序总这么臃肿呢?为什么感觉.NET写出来的程序就总是那么慢呢?我不知道这样的问题有谁思考过,反正我的结论是这样的:

1、如果说某A用C++写出来的程序,总是一会儿访问非法地址,一会儿内存泄露,再一会儿发现case没有break导致“命令指针“飞流直下三千尺,不到黄河不落泪”,你会对某A下一个什么结论?好听点:此公逻辑不严谨,基础不扎实,做事粗心大意;难听点:拖出去毙了。

那么在C#上面呢?哎,居然某A写的程序能跑!你觉得是好事还是坏事?我觉得很难下一个绝对的判断,反正呢,用人成本肯定变低了,副作用是你能看到越来越多很臭的代码。估计Linus可能是因为同样的原因,受不了C++圈子而在特定的条件下选择用C。(不知道当年用汇编出身的老爷爷们如何看到Linus的?)

2、当你用C++的时候,你敢假设每一个对象都会被正确销毁吗?能够完全不写delete obj吗?我觉得很难吧?至少我以前就是觉得这是C++开发中一个重要的脑力活动之一。现在当你使用C#的时候,你突然发现竟然不用考虑了,你有管家替你收拾满地的臭袜子了,于是你会毫无节制的制造对象,直到发现系统撑不住了才意识到问题严重性。呵呵,消费总是有快感的,结账你才能感到痛。GC给你打了麻药了,你说呢?

3、当你回过头来看前面两条,你会发现,原来你也是制造这部分问题的罪魁祸首之一啊!补充一下:谁在用C#开发的时候,注意过struct是在栈上分配,class是在堆上分配的?谁会真的说在函数内部的临时变量,尽量使用struct类型?没有吧?

其实,如果经过仔细选型而是用了C#,那么大多是因为要高开发效率和低开发成本的。(哪个用C#开发气象数据分析或者核弹爆炸模拟,真是不要命了。)在这么个前提下,整个项目组的要求必然是效率至上,什么性能啊、内存啊,只要还没有出人命,那就先放在第二优先级上。哦,忘了提了,很抱歉,我们只有时间做第一优先级的东西,甚至可能还要把其中的一半调整到第二优先级。如果实在不行了,先加硬件再说,加不了的(比如其实那时客户端)再考虑怎么改进,不过通常到了这步基本上已经会发现整个代码很悲剧了,好点的要针对某个部分动个规模不小的手术,惨点的就推到重来。甚至会懊恼怎么选了一个这么个玩意儿,干脆改回用C++。

 

人月神化说过,对一个已经进度落后的项目,如果仅仅增加更多的人手,而不做任何其它的调整,只能让进度更加落后。我也凑个热闹:

对一个已经出现性能问题的项目, 如果仅仅换一个更高效的语言或者平台,而不做任何其它的调整,只能爆发更多的问题。(因为人没变,却选择了对人素质要求更高的东西。)

 

[回顾]

那么我之前那两篇都说了些什么呢?再这里,为了展示前因后果,我需要引述一下firelong的原文,如果有任何“断章取义”的嫌疑,那不是我的本意,我想大家最好仔仔细细、认认真真地看看所有原文再来评论。

 

firelong在“http://www.cnblogs.com/firelong/archive/2010/06/20/1761357.html”这里提到:

"7. Linq(去掉,还是用Sql语句+存储过程来的实际)" 

于是,我在“http://www.cnblogs.com/sumtec/archive/2010/06/21/1761392.html”这里指出了以下几个问题:

1、Linq不等于Linq2Sql,这里有点逻辑不严谨; 

2、Linq2Sql是.NET Framework的一部分,而不是C#增加的语言特性;(诸位非要说.NET == C#,Linq == Linq2Sql,然后指责我偷换概念,那就说吧,只要大部分人能认同就可以了)

3、Linq这个C# 3.0 增加的语言特性,实际上提高了生产效率;

4、Linq在实际上有可能比传统编写方式在运行效率上更加高。(仔细看看写的实例。)


有关这样一点,我特别想听听firelong是如何评论的,因为之后没有说我对您所挑的刺是对是错,就开始说C#慢了。

 

后来,firelong在“http://www.cnblogs.com/firelong/archive/2010/06/22/1762376.html”这里提到:

Firelong首先来谈性能问题,这是C#语言在不断塞入新功能后所带来的最严重的问题。”

下面开始摆事实。”

那么摆了什么事实呢?我斗胆归结如下:

1、“飞信(以前用过C#开发,后来受不了改回C++了)” 

2、客户端“任何一个领域,大家能找出哪怕1-5款在全世界或中国流行的客户端软件是用C#写的吗?”

3、“特别搞的是其中有一个公司的首席架构师就是从微软总部挖过来的,大家都以为他最支持C#,没想到他否定C#否定的最厉害。”

4、“至于Windows操作系统——这算最大的客户端了吧!我压根就没期望这辈子能看到它用.NET开发!参见李开复博客:http://blog.sina.com.cn/s/blog_475b3d560100h4il.html ,注意其中几句话:……” 

5、 “我本以为Expression Studio微软会用什么C#性能提升秘籍来搞,提振大家对C#的性能信心,希望研究学习学习。但是我真正跑了几次就郁闷了,我估计它几年后的命运和Windows Vista差不多。”

6、网站上面,根据Alex或者Google排名,“网站排名中,数一数有几个是.NET开发的?”

7、“C#自2000年问世以来,在全世界或者全中国,到底搞出来了几个响当当的,能拿出手的,亿万用户喜闻乐见的软件了?”

主要可以归结为:无法列举出知名软件是使用.NET来开发的,甚至有从.NET转型到C++的,证明这是因为C#慢;某人(不知道是谁在何处)说过,就是慢;Vista上的应用用.NET开发失败了,是因为慢。 

 

那么我在“http://www.cnblogs.com/sumtec/archive/2010/06/22/1762564.html”这里,又说的是什么呢?我主要指出的,依然是逻辑不严谨,例如:

1、firelong并没有指出C#的慢是相对什么而言的。事实上类似的问题还有“这就对了,firelong给企业应用的解释就是“即便性能不咋样,客户也可以接受的软件叫企业应用!” ”,这里面的企业级应用仍然不能很好的定义出,什么样的是企业级应用,于是完全无法讨论。比如说,招行的网络银行算反例吗?

2、firelong的文章中,并没有给出多少可信服的数据作为支撑。在我替firelong假设了比哪些语言慢的前提下,举了一些简单的例子,说明我们无法简单的得到一个C#比PHP慢的结论。诸位:证明一个理论是失败,或者至少不是完全成功的,只要能举出反例即可。但是要证明一个理论是成功的,却相当的困难。比如,我用任何两个物体之间的相对速度不可能超过光速,即可证明牛顿力学是不准确的。但是要证明爱因斯坦的相对论就完全正确,这就难多了。可是更有意思的是,很多人却会因为爱因斯坦举出“任何两个物体之间的相对速度不可能超过光速”这么一个实例,就认为爱因斯坦试图以此证明他的理论是正确的。重申:我并没有证明C#就是绝对的快。

3、我指出,试图从“排名靠前,或者某个人知识范围内所认知的知名软件不使用C#开发”得到“C#慢”这个结论是非常不严谨的。这点我不多说了,可以看看统计学的书;

4、最后再次指出,其第一篇文章中觉得或者认为C#慢,因此提议去掉Linq这个要求,是矛盾的。这里面举了一个Jeffrey的试验例子。这一点是期望firelong能回归到我的第一个帖子中提出的一些问题中去。

 

当然了,我一篇文章只能针对比较小的范围做打击,很遗憾漏掉了一些,这里我补充提出其它的论证问题:

1、“特别搞的是其中有一个公司的首席架构师就是从微软总部挖过来的,大家都以为他最支持C#,没想到他否定C#否定的最厉害。”这是谁,在什么时候,在什么可以查证的地方说过?在法律上讲,如果没法查证,可以认为是造谣。当然,我觉得也确实觉得很可能真有这么一个从微软出来的一个人,也确实这么说过,他这么说也可能真的是有道理的。问题是,你没有办法以这一句话本身作为实事证据。好比如果我说“我认识一个PP公司的员工,说他们公司用.NET开发新一版的即时通讯软件,发现性能比原来用C++做的那个旧版本快10倍”一样,别人要问雅点只能说这没有证据,垃圾点的就会骂我bullshit。我觉得除此之外还能有什么样的可讨论角度;

2、“至于Windows操作系统——这算最大的客户端了吧!我压根就没期望这辈子能看到它用.NET开发!参见李开复博客:http://blog.sina.com.cn/s/blog_475b3d560100h4il.html ,注意其中几句话:……”。没错,C#对于开发操作系统,甚至是上面最经常使用的附带软件来说,都是太慢了(目前而言)。但那也是选型工作没有做好而导致的决策灾难而已,不能证明C#在任何企业应用环境中都是慢得无法承受,或者至少说用这么一个例子来说有点薄弱和牵强。如果说Linus那天打算用Javascript开发下一版本的Linux且最后失败了,你觉得应该抱怨javascript慢呢,还是应该抱怨Linus的选择有问题?

 

[现状]

我觉得有点杯具的是,firelong既不承认,亦不否认我所提出的这些问题说得是否在理,就又开始继续往前飞奔到“C#慢的其中一个原因是MetaData占比重太大”这个主题上。所以,我觉得有人觉得这是一系列公关文,可能这也是其中一个原因吧。那么这篇新文章“http://www.cnblogs.com/firelong/archive/2010/06/24/1764597.html”当中,我想提出下面这一系列问题:

1、如果删掉了MetaData,.NET Framework中哪些东西会受到影响,并且这些东西是否存在不依赖MetaData的其它等价方式。换句话说,我们需要为删除MetaData而放弃什么样的特性(比如说GC?啊,我随便乱说的,举个例子。);

2、删掉了MetaData,对于Linq来说,是会变得更快呢,还是更慢?据我所知,MetaData从1.0到现在都存在,在这个变量受控,以及开发效率变量受控的情况下,Linq比非Linq开发方式,在运行性能上来说是有一定优势的。 是否说MetaData的存在与否,和Linq要删掉没有关系?我确实不能理解,这种.NET平台的问题,和C# 1.0 -> 2.0 -> 3.0 -> 4.0增加的越来越多的语言特性之间,有什么性能损失上的关联(而且还是一直就存在的)。也许感情打一开始就不是在抱怨C#加入了越来越多的新特性,导致越来越臃肿,进而导致越来越慢了;

 

3、删掉了MetaData,对于性能的提升来说,能减少多少比例的时间开销?嗯,我知道,这个实验很难做,我对此深表同情。不要错误理解我的意思,我确实认为这个是一个拖累.NET性能的原因之一,也很期待在这方面有所改进(不一定非要删掉)。不过没有具体数据的话,那就像是在我背上痛恨已久的地方挠了一下痒痒一样,实际上还是没有学到什么实质的知识,也没有很具的一个感官认识。说Meta的占比,我就印象深刻,我就会认真回忆一下那个什么混淆器,好像是可以去掉Meta的(看来真要翻一下了)。

 

技术上的问题,我想先到此结束吧。接着还有一些的其它方面的问题,相对技术问题会让更多的人感到更加不舒服:

1、mspaint和paint.net是一回事么?谁能开一个帖子,给一个功能列表对比?

2、我属于“老赵们”中的一员吗?或者,“老赵们”和四人帮一样属于有限确定集合,还是属于“臭老九”这样有限不确定集合?

当然,有人说了“本文中的“老赵们”指的是那些天天拿着C#语言新特性耍酷表演、而不研究真实技术问题的“所谓的技术精英们”,并不特指老赵一个人,或者老赵的每一个阶段”,不过这仍然属于一种很不好的做法,这种做法如果不予以强烈谴责(尽管特别声明不针对任何人),否则只会把整个讨论的气氛搞坏。为此,我觉得很有必要牺牲自己一把,呼吁“firelong党”不要再一边呼吁别人不要扣屎盆,一边使用“firelong党”这种除了挑事没有别的含义的称呼,直到这些人认识到自己的错误并表示不再犯为止。

P.S. 本文中的“firelong党”指的是那些整天使用幼儿园小朋友起别人花名、乱扣帽子、大范围无差别攻击的“所谓的技术精英们”,并不特指firelong一个人,或者firelong的每一个阶段(firelong除了扣别人屎盆子的时候,并且给出有意义数据的时候,还算在研究真问题)。 

上述说法是谁听了都难受,我上面说的部分也并非事实,但是谁也难保自己说的就是事实,因此这么说其实别人有多生气,你很难感受到。当然了,有的人即便我这么说,还是不能感觉到,那只能说我往下降的层次还是不到位。不过那些人就不在我想要沟通的范围内了,我也先说明我是不会回应的。这里也先给firelong道个歉了,我觉得上面那种说法对你是很过分的。

 

3、说老赵抄袭.NET技术大会上Jeffrey Richter老人家show的性能计数器的证据是什么?(我真的是想知道,我一定会根据决定在这个问题上我站在哪一边讨伐另一边)

4、“不是拿个CodeTimer这样的玩具输出几个时间值,就拍脑袋下结论的。”    和 

我相信我在前文举出的很多世界著名、或者中国著名的软件最终没有选择.NET,都有过这样一个评测过程。”

这两种论证方式哪一种更客观事实?比如我说“Linq比非Linq开发方式的代码相比,执行效率高30%,因此在这种情况下,是比较快的”,这是一种事实陈述。“我相信Linq比非Linq开发方式的代码快,那是所有大公司里面工作了5年以上的员工都知道并承认的”,这是一种主观想法。主观想法中所描述的内容,恰恰是需要通过事实陈述来支持或者反驳的;

 

最后,我需要对“http://www.cnblogs.com/firelong/archive/2010/06/24/1764597.html”这一文中最后所提出结论逐条回应: 

1、firelong说我的文章“测量的只是某一个微观代码段的性能”,而我实际上只是想以此说明,之前的“不可承受之慢”一文当中,存在范围过大的问题。我举例说,没有对比的语言,然后再举例应该类似这样的对比才有意义。自然,有意义的对比必须很明确,我这里假设的就是在微观状态下。因为这样的证据比较好找,而大型软件因其算法很难一致,因此很难进行有意义的、公平的、公允的比较。当然了,我自然知道这种微观比较没有太大的意义,因为总体性能而言,不是这么一两个微观细节决定的。如果是我的话,更注重算法本身的改进。所以我才一直说,我觉得我用C#并不会在意快慢问题。我要说的是你之前文章的逻辑问题,没想却被你曲解和错误借用;

2、虽然我不知道你说的老赵们是否包括我,我还是想声明:我没有对这个问题作出选择,因为我没有打算否认这些问题;

3、“B/S应用的服务端添加硬件,在提高性能上比软件修改,在一般情况下(即算法本身没有大问题时),比改进算法更具备性价比” 我是在回复里面说过,但这不能够引申为“可以通过添加硬件来达到企业级应用的标准”;

4、我认为C#跟Java比才具备意义,不是说Java是我们班倒数第一的(这个结论firelong是怎么得出来的?),所以我们要力争倒数第二。而是因为,Java和C#市场的重叠性很高,在进行技术选型的时候,如果最后得出选择java的结论,那么很多时候C#也应该是当初的候选考察对象之一。当然了,有些时候平台限制,开发人员限制,第三方软件限制,这些会导致java更胜一筹。如果你是在这个问题上面炮轰C#的话,我估计大部分人会该干啥干啥。偏偏你选择的是一个比较标新立异,而且还要把C#说成是拉java做垫背的,那就没办法招来这么多不理智的回复了。 在同样面对的市场范围内,比如说吧,网站服务端,你认为更好更快的开发语言是什么?我觉得这么说说还比较有意思。


后记:

个人只是想提倡学术讨论要严谨,包括逻辑和用词。对于C#慢不慢,比谁慢什么的,都不是太感兴趣。因为一个产品使用什么语言开,快慢只是其中一方面,很多时候光是你老板说了算就一点办法都没有。我想起来一个笑话:

老师问:现在桌子上有12块钱,但是一共有5个小朋友,哪位同学能告诉我,这个钱他们应该怎么分?

同学甲:先杀了一个小朋友…… 

 

当然如果是劝大家不要学习C#,换一份工作,那又是另外一回事。(如果那样的话,还不如说,你看C++的市场还是比C#要大的,甚至PHP都几乎是C#的两倍,这才比较符合阅读者的切身利益。)不过C#占有率不断提升,也不是这么一两篇文章的推动就能阻止的。Linus骂了C++之后,C++不还是在很靠前的排名上吗?博客园是否真的要开始一场娱乐化的盛宴,这真要拭目以待了。