是什么决定了编程语言的“速度”?


38

假设一个程序是用两种不同的语言编写的,让它们分别是语言X和语言Y,如果它们的编译器生成相同的字节码,为什么我应该使用语言X而不是语言Y?是什么定义了一种语言比另一种语言快?

我之所以这么问,是因为经常看到人们说这样的话:“ C是最快的语言,ATS是和C一样快的语言”。我试图了解编程语言“快速”的定义。


21
如果一个程序比另一个程序快,则意味着它们不能具有相同的字节码。
svick

5
语言只是人们编写程序的一种概念,因此您不能真正谈论语言的速度
Juho 2015年

1
@Raphael我觉得它是题外话,不清楚并且过于广泛。尽管该主题更适合于软件工程,但我认为该主题可能会因为“过于广泛”而被关闭。
David Richerby

2
实施不谈,“速度”是不明确的,有不同的速度执行,编译,执行和调试,而你通常会被交易掉一些对别人(否则我们就都可以使用编程语言)
尼克T

如上。这些语言不会生成相同的字节码。一些语言更容易解析为字节码。有些具有更高的抽象水平。
2015年

Answers:


23

选择语言X而不是语言Y可能有很多原因。程序易读性,易于编程,可移植到许多平台以及存在良好的编程环境都可以成为此类原因。但是,我将仅考虑问题中要求的执行速度。例如,这个问题似乎没有考虑发展速度。

两种语言可以编译成相同的字节码,但这并不意味着将生成相同的代码,

实际上,字节码仅是特定虚拟机的代码。它确实具有工程优势,但不会直接针对特定的硬件进行编译而带来根本的区别。因此,您不妨考虑比较为在同一台计算机上直接执行而编译的两种语言。

也就是说,语言的相对速度问题是一个古老的问题,可以追溯到第一个编译器。

多年来,在早期,专业人员认为手写代码比编译代码要快。换句话说,机器语言被认为比高级语言(例如Cobol或Fortran)更快。而且速度更快,通常更小。高级语言仍在发展,因为它们对于许多非计算机科学家来说更易于使用。使用高级语言的代价甚至有个名字:扩展率,它可能与所生成代码的大小(在当时是一个非常重要的问题)或实际执行的指令数有关。这个概念主要是实验性的,但是比率最初大于1,因为按照当今的标准,编译器的工作相当简单。

因此,机器语言比说Fortran更快。

当然,多年来,随着编译器变得越来越复杂,这种情况发生了变化,以至于汇编语言的编程现在非常罕见。对于大多数应用程序而言,汇编语言程序与优化编译器生成的代码的竞争较弱。

这表明一个主要问题是可用于所考虑语言的编译器的质量,它们分析源代码以及相应地对其进行优化的能力。

此功能可能在某种程度上取决于语言的功能,以强调源的结构和数学属性,从而使编译器的工作更加轻松。例如,一种语言可以允许包含有关用户定义函数的代数属性的语句,以便允许编译器将这些属性用于优化目的。

当语言的编程范例更接近于将要解释代码的计算机的功能时,无论是真实的还是虚拟的,编译过程可能会更容易,从而产生更好的代码。

另一点是,用该语言实现的范例是否接近正在编程的问题类型。可以预期,专门用于特定编程范例的编程语言将非常有效地编译与该范例相关的功能。因此,为了清楚和速度,编程语言的选择可以取决于适合于正被编程的问题种类的编程语言的选择。

C在系统编程中的流行可能是由于C接近于机器体系结构,并且系统编程也与该体系结构直接相关。

使用逻辑编程和约束解析语言可以更快地执行一些其他问题,从而更容易编程。

复杂的反应系统可以使用像Esterel这样的专用同步编程语言进行非常高效的编程,该语言体现了有关此类系统的非常专业的知识,并可以生成非常快速的代码。

再举一个极端的例子,某些语言是高度专业的,例如用于对解析器进行编程的语法描述语言。一个解析器生成器也不过是这种语言的编译器。当然,它不是Turing完整的,但是这些编译器在其专业方面非常有用:生成高效的解析程序。由于知识领域受到限制,优化技术可以非常专业化并进行非常精细的调整。这些解析器生成器通常比通过用另一种语言编写代码所获得的解析器好得多。有许多具有编译器的高度专业化的语言可以为受限的问题类别生成出色而快速的代码。

因此,在编写大型系统时,建议不要依赖单一语言,而应为系统的不同组件选择最佳语言。当然,这引起了兼容性问题。

通常重要的一点是,对于正在编程的主题,仅存在有效的库。

最后,速度不是唯一的标准,并且可能与其他标准(例如代码安全性(例如输入错误或对系统错误的适应性),内存使用,易于编程)相冲突(尽管范式兼容性实际上可以帮助),目标代码大小,程序可维护性等

速度并不总是最重要的参数。同样,它可能采取不同的形式,例如复杂度可能是平均复杂度,甚至可能是更糟的情况。同样,在大型系统中,在较小的程序中,某些部分的速度至关重要,而其他部分的速度则无关紧要。事先确定并不总是那么容易。


谢谢。它是这样的。我正寻找。很难找到适合该主题的材料。这足够澄清。
Rodrigo Valente

@RodrigoAraújoValente谢谢,您不妨看一下这个问题。一种极端的观点是,语言L的编译器可以将语言L的解释器与程序的源代码捆绑在一起,而无需执行任何操作。然后,通过尝试优化捆绑软件的计算(部分评估)可以做得更好。优化越多,语言就会越快。问题是:什么可以帮助您优化?答案可能包括对专业领域的深入了解,程序员的帮助,复杂的分析等……

所谓“相同的字节”我猜你的意思是“同一类型的可执行表示的”。显然,相同的可执行文件将以相同的速度运行(假定相同的执行系统)。(我可能会从信息/通信的角度来看这件事。从理论上讲,程序员可以了解有关程序和硬件的所有信息,而语言通常会限制通信(限制允许或有用的转换),而编译器可能不知道微体系结构详细信息。编译和编译器开发是对开发和培训的分析..
Paul A. Clayton

然后,这涉及到人类通常擅长的领域(例如,识别一般模式)与计算机通常擅长的领域(例如,记录保存和“算术”)。此外,运行时信息的通信通常更友好于计算机(配置文件引导的优化可以克服通过编程语言传达的信息的某些不足)。动态优化对于人类程序员而言是不切实际的……
Paul A. Clayton

(尽管可以由专门针对特定硬件的程序员组装所有软件来编写所有软件,但在对软件进行优化时,不仅硬件会发生变化,软件也会过时。)
Paul A. Clayton

16

虽然所有内容最终都在CPU *上运行,但是不同语言之间存在各种差异。这里有些例子。

解释的语言有些语言是解释型的,而不是编译型的,例如Python,Ruby和Matlab。这意味着Python和Ruby代码不会编译为机器代码,而是即时进行解释。可以将Python和Ruby编译为虚拟机(请参阅下一点)。另请参阅此问题。由于各种原因,解释的速度通常比编译的代码慢。解释本身不仅会很慢,而且很难进行优化。但是,如果您的代码大部分时间都花在库函数上(例如Matlab),则性能不会受到影响。

虚拟机某些语言被编译成字节码,即字节码,然后被解释为“机器码”。典型的示例是Java和C#。尽管字节码可以即时转换为机器代码,但代码运行速度可能仍然较慢。对于Java,虚拟机用于可移植性。对于C#,可能还有其他一些问题,例如安全性。

开销一些语言以安全性为代价。例如,某些版本的Pascal会检查您是否没有超出范围的数组。C#代码是“托管的”,这是有成本的。另一个常见的示例是垃圾回收,它可以节省程序员的时间,但效率不如进行内存管理。还有其他开销来源,例如用于异常处理或用于支持面向对象编程的基础结构。

*实际上,当今的高性能系统还可以在GPU甚至FPGA上运行代码。


那么,基本上,如果我需要更高的性能,那我应该选择编译语言吗?关于范式?选择功能而不是oop是有原因的,反之亦然吗?
罗德里戈·瓦伦特

您关于垃圾回收的评论有点简单。当不再使用分配的内存时,它并非总是可以静态确定的。即使可以确定,也很难确定而不出错。因此,GC有时是必需的,而且通常更安全(例如checkingarray范围)。此外,它可以与显式发布结合。
2015年

@RodrigoAraújoValente取决于。糟糕的代码通常会编译成糟糕的代码。也许代码,你可以用Python编写实际上比代码要快,你可以在C编写
拉斐尔

尼特:正如您所链接的问题所解释的那样,实际上并没有“实时”解释python :)
Eevee 2015年

您在解释部分中提到的所有语言均不会即时进行解释。Python已编译为字节码,Ruby已编译为AST,但我相信现在已编译为字节码。Matlab,我相信现在实际上是JIT编译的。实际上,我不知道有任何非小众语言实现可以即时解释事物,至少不可以编译为某种虚拟机表示形式。
温斯顿·埃韦特

5

选择X而不是Y有多种因素,例如

  • 易于学习
  • 易于理解
  • 发展速度
  • 帮助执行正确的代码
  • 编译代码的性能
  • 支持的平台环境
  • 可移植性
  • 适合用途

某些语言适合于开发C#或Python之类的业务项目,但另一方面,其中一些语言则适合于诸如C ++的系统编程。

您必须确定要在哪个平台上工作以及要创建什么应用程序。


1
那么,如何确定编译后的代码的性能呢?这基本上就是让我做这个问题的原因。
罗德里戈·瓦伦特

6
这个答案当然有很好的建议,但是我看不出它是如何回答这个问题的。
15

@RodrigoAraújoValente它们甚至可能不是经过编译的代码(如果您的语言已被解释)。
拉斐尔

1
您可能要添加“良好的库”和“良好的工具”。
拉斐尔

@RodrigoAraújoValente您可以运行它并对其进行配置。
凯尔(Kyle)

2

在任何平台上都能获得的“最快”编程语言是您要处理的芯片组的汇编语言。在那个级别上没有翻译。但是,需要了解芯片组如何执行指令,尤其是那些可以并行执行指令的指令。

从C到汇编的转换非常“浅”,几乎一对一,但是可读性更高。但是,由于使用了标准库来提高可移植性,因此它上面有很多层。编译器不需要太多的工作来获得汇编代码,并且通常存在更强的优化以进行机器特定的更改。

C ++添加了更丰富的语言。但是,由于该语言增加了太多的复杂性,因此编译器很难为平台创建最佳代码。

然后我们转到秤的另一端。口译语言。这往往是最慢的,因为除了完成工作外,还花费一些时间来解析代码并将其转换为机器调用。

然后,我们将它们夹在中间。通常,它们具有针对平台优化的虚拟机层。然后编译器将创建代码供虚拟机执行。有时,这会像perl或pascal或ruby或Python一样同时发生。或像java这样的几个阶段。

其中一些虚拟机添加了JIT编译器的概念,它可以通过创建计算机级别的代码而不是转换中间字节代码来加快运行时间。

某些虚拟机级别较低,因此从字节码到机器码的转换较少。在保持可移植性的同时加快速度。


从历史上看,C被设计为允许轻松转换为机器代码。但是,将C转换为有效的C代码的程度越来越高,要求编译器弄清楚程序员试图做什么,然后将其转换为机器代码。例如,从历史上看,与*p++=*q++;许多机器上等效的机器代码比以前要快,array1[i]=array2[i];但是在许多处理器上,情况恰恰相反,因此编译器可能最终将前一种代码样式转换为后者,这几乎是“浅”转换。
超级猫

通常这就是您-O0所做的任何优化。优化是使用编译器获得的好处,但是语言本身可以将几乎一对一的语言翻译为汇编语言。
Archimedes Trajano

2

还没有提到的一点是,在某些语言中,多次运行同一段代码将始终执行相同的操作序列;因此,计算机只需确定一次代码部分应该做什么。JavaScript的“严格使用”方言的主要好处之一是,一旦JavaScript引擎确定了一段代码的功能,它就可以在下次运行时利用该信息。没有“严格使用”,就不可能。

例如,在没有“ use strict”的情况下,一段代码如下:

function f() { return x; }

可以在立即调用上下文中返回变量X(如果有的话),或者可以在外部调用上下文中返回变量X,或者可以返回Undefined。更糟糕的是,像这样的循环中:

for (i=0; i<40; i+=1) { g(i); }

JavaScript引擎无法知道g()对此有何影响i[或对其g本身有什么影响。由于gi可以完全合法地更改i为字符串,因此JavaScript引擎不能在循环中简单地使用数字加法和数字比较,而是必须在每次循环中检查是否有函数调用对i或进行了任何操作。g。相比之下,在“严格使用”(比较合理)的方言中,JavaScipt引擎可以检查上面的代码,并知道每次循环都将使用相同的数字变量并调用相同的函数。因此,它仅需标识i并起作用g 一次,而不是每次循环都要查找它们-节省大量时间。


2

好吧,这里有一些非常专业的答案,虽然这个答案与他们不太接近,但对您来说可能很直观。

您可能已经多次听到,当您需要尽快执行任务时,您将需要编写在汇编中执行该任务的代码。这是因为您仅执行完成任务所需的命令,仅此而已。虽然您可以使用高级语言来分几行实现此任务,但是编译器仍然需要将它们翻译为机器语言。由于您可以直接编写此翻译,因此它并不总是简约的。这意味着机器将花费许多时钟来执行您可以节省的命令。

尽管当今的编译器非常复杂,但它们仍然无法像最好的汇编程序员一样有效。

继续朝这个方向发展,这些不需要的命令的数量(通常)随着语言的高级化而增加。(并非所有高级语言都100%正确)

所以对我来说,如果对于某些代码,X的机器代码比Y的机器语言短(在运行时),X的语言要比Y的语言快。


组装完全动摇。不过,需要一位真正的艺术家才能胜过最好的编译器。
约翰,

1

很难确切地回答这个问题,因为它是如此复杂和多维(这几乎就像比较汽车品牌和其他标准一样),但是有新的科学研究,包括一个称为Rosetta code的优秀代码存储库(维基百科概述)。Nanz和Furia于2014年进行的这项调查基于以下典型标准以及对典型主观代码质量的罕见定量分析,非常明确,科学地研究了这个问题。摘要包含一些客观依据的发现和概括。(希望将来可以在这些结果的基础上进行其他研究。)

  • RQ1。哪种编程语言可编写更简洁的代码?

  • RQ2。哪些编程语言可编译成较小的可执行文件?

  • RQ3。哪种编程语言具有更好的运行时性能?

  • RQ4。哪种编程语言更有效地使用内存?

  • RQ5。哪种编程语言不太容易出错?

摘要—有时,关于编程语言的辩论比科学更具宗教性。人们热烈地讨论了关于哪种语言更简洁或更有效,或者使开发人员更具生产力的问题,而他们的答案往往基于轶事和没有根据的信念。在这项研究中,我们利用了Rosetta Code尚未开发的潜力,Rosetta Code是使用各种语言解决常见编程任务的解决方案的代码存储库,可提供大量的分析数据集。我们的研究基于7,087个解决方案程序,它们对应于8种广泛使用的语言中的745个任务,这些语言代表了主要的编程范例(过程:C和Go;面向对象:C#和Java;功能:F#和Haskell;脚本:Python和Ruby)。我们的统计分析最明显地表明:功能和脚本语言比过程和面向对象的语言更简洁;在大型输入的原始速度方面,C很难被击败,但是在中等大小的输入上的性能差异不太明显,甚至使解释型语言也具有竞争力。与解释型或弱类型语言相比,编译型强类型语言在编译时可能会捕获更多缺陷,因此它们在运行时失败的可能性较小。我们讨论了这些结果对开发人员,语言设计师和教育工作者的影响。与解释型或弱类型语言相比,在编译时可以捕获更多缺陷的地方,运行时失败的可能性较小。我们讨论了这些结果对开发人员,语言设计师和教育工作者的影响。与解释型或弱类型语言相比,在编译时可以捕获更多缺陷的地方,运行时失败的可能性较小。我们讨论了这些结果对开发人员,语言设计师和教育工作者的影响。


0

计算机语言只是用于解释计算机操作的命令的抽象。

您甚至可以用计算机语言Python编写并使用C编译器(cython)进行编译。

牢记这一点,无法比拟计算机语言的速度。

但是您可以在某种程度上比较同一语言的编译器。例如GNU C编译器与Intel C编译器。(搜索编译器基准)


2
如果您想对问题发表评论,请使用评论框,而不是您的答案。请注意,这是计算机科学堆栈交换,计算机科学不是编程,就像文学不是文字处理一样。有关软件工程堆栈溢出的编程问题。
David Richerby 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.