不。
动态语言并不比静态语言慢。实际上,任何语言(不管是动态还是静态)都不可能比另一种语言“更慢”(或者“更快”),因为一个语言只是一堆抽象的数学规则。你不能执行一堆抽象的数学规则,因此它们永远不可能变慢或变快。
“动态语言比静态语言慢”这个说法不仅是错误的,而且毫无意义。如果英语是静态语言,那么这个说法甚至无法通过类型检查。
为了使一个语言能够运行,它首先必须被实现。现在你可以衡量性能,但你测量的不是语言的性能,而是执行引擎的性能。大多数语言都有许多不同的执行引擎,具有非常不同的性能特征。例如,对于C语言,最快和最慢的实现之间的差距约为10万倍!
此外,你也不能真正地测量执行引擎的性能:你必须首先编写一些代码在该执行引擎上运行。但现在你测量的不是执行引擎的性能,而是基准代码的性能。这与执行引擎的性能几乎没有关系,当然也没有任何关系了语言的性能。
总的来说,在高性能的好设计的执行引擎上运行良好设计的代码将产生大约相同的性能,无论语言是静态还是动态、过程化、面向对象还是函数式、命令式还是声明式、惰性还是严格、纯洁还是不纯洁。
实际上,我认为一个系统的性能完全取决于投入的资金数量,而与任何特定的类型学科、编程范式或语言无关。
以Smalltalk、Lisp、Java和C++为例,它们都是高性能代码的首选语言,或曾经是。这些语言都经历了大量的工程和研究时间来使它们变得快速。它们都有高度优化的专属商业高性能执行引擎可用。在大致相同的问题实现下,由大致类似的开发人员实施,它们的性能都差不多。一般情况下,如果其他条件相同,是的。
首先,你必须澄清你是否考虑:
通常我们的意思是:
但这不一定是情况。
类型信息可以帮助虚拟机比没有类型信息更快地分派消息,但随着虚拟机中检测到单态调用站点的优化,差异往往会消失。请参见此有关VM中动态调用的文章中的“性能考虑”段落。
编译 vs. 解释 vs. 字节码JIT之间的争论仍然存在。一些人认为,字节码JIT导致比普通编译更快的执行,因为由于收集的更多信息在运行时,编译更准确。阅读JIT的维基百科条目以获取更多见解。解释语言确实比两种编译形式都慢。
我不会进一步争辩或开始激烈的讨论,我只想指出,两者之间的差距往往越来越小。你可能面临的性能问题很可能与语言和VM无关,而是与你的设计有关。
编辑
如果你想要数字,我建议你查看计算机语言基准测试。我发现这很有启示性。
在指令级别上,目前动态类型语言的实现通常比静态类型语言的实现慢。
然而,这并不一定意味着使用动态语言实现程序会更慢 - 许多文献中都有同一个程序分别用静态语言和动态语言实现的案例,其中动态实现往往更快。例如,这项研究(PDF)将同一问题交给了使用各种语言的程序员,并进行了比较。Python 和 Perl 实现的平均运行时间比 C++ 和 Java 实现的平均运行时间更快。
这有几个原因:
1)在动态语言中,代码可以更快地实现,留下更多时间进行优化。
2)高级数据结构(映射、集合等)是大多数动态语言的核心部分,因此更有可能被使用。由于它们是语言的核心部分,所以它们往往被高度优化。
3) 程序员的技能比语言速度更重要——一个缺乏经验的程序员在任何语言中都可以编写较慢的代码。在上述研究中,每种语言中最快和最慢实现之间有几个数量级的差异。
4) 在许多问题领域,执行速度受到I/O或其他外部因素的支配,与语言无关。
5) 算法选择可能使语言选择相形见绌。在书籍《More Programming Pearls》中,Jon Bentley为一个问题实现了两个算法——一个是O(N^3),在Cray1上针对Fortran进行了优化。另一个是O(N),在TRS80家用微型机上使用BASIC实现(这是在1980年代)。当N> 5000时,TRS80表现优于Cray 1。
最重要的因素是考虑方法分派算法。在静态语言中,每个方法通常被分配一个索引。我们在源代码中看到的名称实际上在运行时并没有使用,只是为了可读性而存在。当然像Java这样的语言会保留它们,并在反射中使它们可用,但就调用方法时而言,它们并不会被使用。我将在本讨论中省略反射和绑定。这意味着当调用方法时,运行时简单地使用偏移量来查找表并调用。另一方面,动态语言使用函数名称来查找映射,然后调用该函数。哈希映射始终比在数组中使用索引查找慢。
可以合理地假设,随着运行时需要计算的事物越来越多。