• 致那些吐槽.NET性能低的开发人员
  • 发布于 2个月前
  • 640 热度
    0 评论
.NET作为开发平台来说,不可否认是优雅的、高效的。可是有些人就是看不到它极高的开发效率,极短的市场推出时间,极强的扩展能力,非得在性能上较劲,把一帮小萌新忽悠得一说起 .NET就觉着是“慢”、“卡”的代名词。

这些人总是存在一个思维误区,认为程序性能是和语言挂钩的。您没事儿吧?真要这样,《数据结构》、《算法》这些课早他妈该撤了好吧。汽车和飞机速度确实不一样,但就算给您一架私人飞机,您能给表演表演每天开飞机去买菜?任何语言的性能瓶颈,大半还是出在使用这语言的人蠢身上。新手司机开着十辆布加迪也不可能拼过驰骋秋名山的五菱宏光老司机。咱们不抬杠,今天就只说性能,不说开发效率、上市速度。非要跟我抬杠,算上这些,可能我的“低性能”产品已经出街了,你憋半天憋不出屁的“高性能”产品快扑街了,优越个🐔8呢。

.NET的开发语言一般用C#,后边我就不区分 .NET和C# 了。F# 其实也差不多,反正最后都编译成intermediate language,可以认为是等价的(函数式编程更多的是一种思想,这个话题我以后会写)。实话实说,C# 这门编程语言,一开始就处于一个挺尴尬的位置。性能上,有C/C++ 在前边拦着;应用上,有Java、Python在后边堵截,不上不下。.NET玩家心里总憋着股邪火,只好左右互搏,自娱自乐了。

语言的比较

这个问题的根源,很大一部分在于很多程序员只会一种语言,甚至连这唯一的语言也不够精通,所以才会要么看不起别的语言,要么埋怨自己这语言性能太弱。想要一招鲜吃遍天,梦里可以,醒来最好还是把这茬给忘了。而那些对 .NET一知半解就开始嘲讽的“别的语言”玩家,就更别指望他们能理解到其中的精髓了。

把自己限制于一种语言的程序员会经常错过其他地方提供的重要机会。这样的程序员绝对不会被他们的老板或客户看成是专业领域中的专家。

——Oliver Sturm

C# 虽然定位尴尬,但是它本身是高度优化的,要比性能,无非就C/C++ 或者汇编才配跟它比。Java、Python这些,大家都是IL解释的,本是同根生,相煎急锤子,都不一定能比过C#。C系玩家就算了,特性使然确实比不过,但是事实上优化之后性能也大差不差(我马上就能证明这一点)。最奇怪的就是好多J、P玩家居然好意思笑话C# 性能辣鸡,完全没意识到自己那惨样儿。就好像宋小宝去够姚明手里的球,结果潘长江在边儿上笑得挺欢,笑您 🐴 呢?和机器码比起来,任何使用中间语言虚拟机/runtime的语言都有损失,这话没人能反驳吧?Benchmark,一般都是用最耗资源的操作——比如图像处理——来比较。这无非就是测试磁盘、内存的IO性能呗。操作系统最终的性能在那卡着,assembly可以达到95%,C系8、90%,C# 可能亏点儿,6、70%的样子。然而,这都不是重点,重点在于,你有没有完全利用到语言的全部特性,以及那些你认为低效率的算法,非要用它们真的大丈夫?40米大刀拿来削苹果,可能它的性能真的很低吧。

我过去的试验

2012年的时候我就测试过用C# GDI+读写bitmap,一开始用的常规算法,很慢。但是经过优化后,性能提升了363倍,我也没用别的任何类库,还是 .NET 2.0原生。您说怎么判断C# 的性能到底是低还是高?

▲ 2012 年的测试,主要内容已经丢失,我在网上找到的爬虫文章
当时一帮哥们儿看了我的试验都手痒秀了一遍优化:

上面这张表,可以看到,几种语言的性能是接近的,相差最大20毫秒(C# vs 汇编)。除了b项C++ 加了buff(当时i7是顶级CPU),换到同平台,基本差不多的。当技巧和算法都优化到极致之后,其实C#、VB、C++ 的性能非常接近了,轻微的差异在大部分场景下几乎是可以忽略的。这一点,我以前这个试验就是很好的解释。计算机技术发展到今天,语言的运行效率差异早就可以忽略不计了,方法论和算法的才是核心。

重新再试验

有人说,跟程序员交流,不要说那么多话,要么秀代码,要么秀妹子。那么我接下来就请出互联网的first lady——瑞典模特Lena Soderberg(展示的样本经过了处理)。Lena的介绍可以看昨天的新闻:《花花公子》的封面女郎,计算机图像界的女神。

▲ Lena/Lenna
测试图我用Lena原图,超高清3831×8192@24bpp,文件大小94.2MB。图像样本可以在 lenna.org 获得。

▲ Playboy 1972 Miss November
拿DIP里最最简单的反色举例,同样用C#,一个萌新和一个大神分别实现,那最后的效率可差老了去了。不信咱来试试。

萌新的实现:单线程managed

这个例子虽然有点儿欺负人,但它确实是实际存在的现象。新手玩家不管是熟练度还是连招都跟老油条没得比。
private void invert(Bitmap bmp) {
  Color sc = new Color();  // 逐像素处理
  for (int i = 0; i < bmp.Width; i++) {    for (int j = 0; j < bmp.Height; j++) {
      sc = bmp.GetPixel(i, j);
      bmp.SetPixel(i, j, Color.FromArgb(0xff - sc.R, 0xff - sc.G, 0xff - sc.B));
    }
  }
}

这种做法理论上是没错的,也能实现效果,就是太慢了。于是萌新可能就开始骂街:C# 真辣鸡,.NET真辣鸡。可是大哥,您这算法就他妈的辣鸡啊!这种单线程的managed语法,想快它也快不起来啊。

▲ 你来告诉我1个核上慢慢摇性能怎么提起来?


大神的实现:并行计算unsafe

大神之所以能叫大神,因为他们可以利用语言以及计算机的全部实力。思路上,他们能够选用最佳的合适算法;技巧上,他们可以挖掘电脑的所有潜力。同样的语言,不同的性能,我再次提出那个问题:你说瓶颈在语言还是在人?


萌新 vs 大神


▲ 同一种语言,同一个任务
看看结果吧!42466ms对上101ms,420倍的差距。谁跟我说 .NET性能差来着?请大点儿声,谢谢!🙏

完毕
其实就上面的例子来说,还能把性能再往上提,但这都是次要的。我想表达的意思已经表达完了:.NET的性能并不低,如果你觉得低,那可能是因为你的能力低。
用户评论