自打学习编程以来,隔三差五都会看到的月经帖之一就是谈论C,C++,JAVA等谁强谁弱,仿佛古龙小说里的兵器谱似的,非得争个一二三,看谁手上的才是“天机棒”。《人月神话》里面说了,软件开发没有银弹;我也要说,编程也没有神兵利器,编程是一种技艺,拼得是心血,多想多练才能出好活。比较各种编程语言就好比是比较苹果和蔬菜,但是如果非得比一比,其实也能学到不少的东西。
首先说大家最关心的性能,首先来给一个定义什么叫做编程语言性能好:同样的事情由不同的编程语言实现,谁有更快的运行速度,谁的性能就好。然后对于这件事,我们可以做如下分析:对于一个给定的问题,比如说判断一个数N是否为素数,我们用最简单的算法,就是看2到sqrt(N)中的自然数k中,有没有能够整除N的。然后根据这个算法,我们可以说其中有一部分是无论用什么语言实现,都必须要做的操作,比如求N/k的余数,并判断余数是否为0,我们称之为“有用计算”;然后相对应的其余部分,都称之为“无用计算”。这样程度的实际运行时间为有用计算和无用计算的总和,然后编程语言的性能就可以拿有用计算的占比来衡量。
第一梯队:大神吐血优化之汇编代码。理论上讲,在给定的机器上,一个大神可以用汇编构造出最优的程序,其中只包含了所有必要的计算(有用计算)并且已经根据系统架构深度优化。这应该是性能最好的编程语言,大家通常说的俗话:”让你快,你丫快得过汇编吗?“就是基于这种现象。
第二梯队:有没有人等着看是C还是C++还是JAVA?你觉得呢?反正我是不会给答案的,编译器的技术发展了,现在这年头对于不同语言到底会带来多少无用计算,真的已经不太容易说清楚了。我只给出一些我的个人看法:
1. 相信编译器,这年头编译器真的已经做了很多很多工作了,尤其是一些成熟的优化编译器,如果你想认真得研究性能问题,甚至连语言的开销也要算上,一定要把无用计算减到最低!那恐怕你得研究编译器的实现了。
2. 坚决抵制:底层 = 高性能 的错误思潮。因为C能写出来的代码都可以用汇编实现,所以汇编的性能就是比C好。因为JAVA虚拟机是用C++写的,所以C++肯定比JAVA快!这是典型的理论上正确,实际上错误的命题。牛逼的编译器相当于一群大神免费帮你改进代码,牛逼的框架,库也是如此,相当于大神帮你做了很多工作。如果你不是神一般的人物,哪怕你自己焊CPU你也搞不出更高的性能,如果你是大神,我知道您是来把这个当笑话看的,我继续您随意……
3. 与其纠结于是不是该鸟枪换炮,不如多看看本语言的最佳实践。当你不明白编程本原的时候,换个语言不过是换种方式写低效的代码,当你明白了编程的真谛的时候,语言不过是通向罗马的条条大路。大道至简,缩减无用计算,简到只有必须的有用计算之后,才是最高效的境界。
4.曾几何时,没有JIT等特性的JAVA虚拟机确实慢。但是现在已经21世纪了。
5.确实有些语言从设计上就需要做更多的“无用计算”,通常这与语言中的对象模型等基础设定有关系,比如保存和跟踪对象的类型信息等。比如一些动态语言,但一般不会太大而且这些动态语言带来的易用性上的好处也是显而易见的。
6.对初学者,不要纠结于编程语言的性能差距,多了解最佳编程实践。如果没有志向搞编译器,平时工作中也别纠结于不同语言的性能差距了,有这时间看看数学,补补基础知识也挺好。
总而言之,编程语言没有快慢,有快慢之分的是各语言的编译器及其运行时环境。语言里的一些特性确实会影响最终生成代码的性能,因为那些特性会影响编译器是否能实行某些特定的优化。这些在语言的设计和演进中也都有所体现,比如C和C++标准中为什么有“未定义行为”,C99标准中增加的restrict关键字;比如C++11中定义了内存模型。这些都是真正关心性能和编译器优化的人很好的材料。