假设一个程序是用两种不同的语言编写的,让它们分别是语言X和语言Y,如果它们的编译器生成相同的字节码,为什么我应该使用语言X而不是语言Y?是什么定义了一种语言比另一种语言快?
我之所以这么问,是因为经常看到人们说这样的话:“ C是最快的语言,ATS是和C一样快的语言”。我试图了解编程语言“快速”的定义。
假设一个程序是用两种不同的语言编写的,让它们分别是语言X和语言Y,如果它们的编译器生成相同的字节码,为什么我应该使用语言X而不是语言Y?是什么定义了一种语言比另一种语言快?
我之所以这么问,是因为经常看到人们说这样的话:“ C是最快的语言,ATS是和C一样快的语言”。我试图了解编程语言“快速”的定义。
Answers:
选择语言X而不是语言Y可能有很多原因。程序易读性,易于编程,可移植到许多平台以及存在良好的编程环境都可以成为此类原因。但是,我将仅考虑问题中要求的执行速度。例如,这个问题似乎没有考虑发展速度。
两种语言可以编译成相同的字节码,但这并不意味着将生成相同的代码,
实际上,字节码仅是特定虚拟机的代码。它确实具有工程优势,但不会直接针对特定的硬件进行编译而带来根本的区别。因此,您不妨考虑比较为在同一台计算机上直接执行而编译的两种语言。
也就是说,语言的相对速度问题是一个古老的问题,可以追溯到第一个编译器。
多年来,在早期,专业人员认为手写代码比编译代码要快。换句话说,机器语言被认为比高级语言(例如Cobol或Fortran)更快。而且速度更快,通常更小。高级语言仍在发展,因为它们对于许多非计算机科学家来说更易于使用。使用高级语言的代价甚至有个名字:扩展率,它可能与所生成代码的大小(在当时是一个非常重要的问题)或实际执行的指令数有关。这个概念主要是实验性的,但是比率最初大于1,因为按照当今的标准,编译器的工作相当简单。
因此,机器语言比说Fortran更快。
当然,多年来,随着编译器变得越来越复杂,这种情况发生了变化,以至于汇编语言的编程现在非常罕见。对于大多数应用程序而言,汇编语言程序与优化编译器生成的代码的竞争较弱。
这表明一个主要问题是可用于所考虑语言的编译器的质量,它们分析源代码以及相应地对其进行优化的能力。
此功能可能在某种程度上取决于语言的功能,以强调源的结构和数学属性,从而使编译器的工作更加轻松。例如,一种语言可以允许包含有关用户定义函数的代数属性的语句,以便允许编译器将这些属性用于优化目的。
当语言的编程范例更接近于将要解释代码的计算机的功能时,无论是真实的还是虚拟的,编译过程可能会更容易,从而产生更好的代码。
另一点是,用该语言实现的范例是否接近正在编程的问题类型。可以预期,专门用于特定编程范例的编程语言将非常有效地编译与该范例相关的功能。因此,为了清楚和速度,编程语言的选择可以取决于适合于正被编程的问题种类的编程语言的选择。
C在系统编程中的流行可能是由于C接近于机器体系结构,并且系统编程也与该体系结构直接相关。
使用逻辑编程和约束解析语言可以更快地执行一些其他问题,从而更容易编程。
复杂的反应系统可以使用像Esterel这样的专用同步编程语言进行非常高效的编程,该语言体现了有关此类系统的非常专业的知识,并可以生成非常快速的代码。
再举一个极端的例子,某些语言是高度专业的,例如用于对解析器进行编程的语法描述语言。一个解析器生成器也不过是这种语言的编译器。当然,它不是Turing完整的,但是这些编译器在其专业方面非常有用:生成高效的解析程序。由于知识领域受到限制,优化技术可以非常专业化并进行非常精细的调整。这些解析器生成器通常比通过用另一种语言编写代码所获得的解析器好得多。有许多具有编译器的高度专业化的语言可以为受限的问题类别生成出色而快速的代码。
因此,在编写大型系统时,建议不要依赖单一语言,而应为系统的不同组件选择最佳语言。当然,这引起了兼容性问题。
通常重要的一点是,对于正在编程的主题,仅存在有效的库。
最后,速度不是唯一的标准,并且可能与其他标准(例如代码安全性(例如输入错误或对系统错误的适应性),内存使用,易于编程)相冲突(尽管范式兼容性实际上可以帮助),目标代码大小,程序可维护性等
速度并不总是最重要的参数。同样,它可能采取不同的形式,例如复杂度可能是平均复杂度,甚至可能是更糟的情况。同样,在大型系统中,在较小的程序中,某些部分的速度至关重要,而其他部分的速度则无关紧要。事先确定并不总是那么容易。
虽然所有内容最终都在CPU *上运行,但是不同语言之间存在各种差异。这里有些例子。
解释的语言有些语言是解释型的,而不是编译型的,例如Python,Ruby和Matlab。这意味着Python和Ruby代码不会编译为机器代码,而是即时进行解释。可以将Python和Ruby编译为虚拟机(请参阅下一点)。另请参阅此问题。由于各种原因,解释的速度通常比编译的代码慢。解释本身不仅会很慢,而且很难进行优化。但是,如果您的代码大部分时间都花在库函数上(例如Matlab),则性能不会受到影响。
虚拟机某些语言被编译成字节码,即字节码,然后被解释为“机器码”。典型的示例是Java和C#。尽管字节码可以即时转换为机器代码,但代码运行速度可能仍然较慢。对于Java,虚拟机用于可移植性。对于C#,可能还有其他一些问题,例如安全性。
开销一些语言以安全性为代价。例如,某些版本的Pascal会检查您是否没有超出范围的数组。C#代码是“托管的”,这是有成本的。另一个常见的示例是垃圾回收,它可以节省程序员的时间,但效率不如进行内存管理。还有其他开销来源,例如用于异常处理或用于支持面向对象编程的基础结构。
*实际上,当今的高性能系统还可以在GPU甚至FPGA上运行代码。
选择X而不是Y有多种因素,例如
某些语言适合于开发C#或Python之类的业务项目,但另一方面,其中一些语言则适合于诸如C ++的系统编程。
您必须确定要在哪个平台上工作以及要创建什么应用程序。
在任何平台上都能获得的“最快”编程语言是您要处理的芯片组的汇编语言。在那个级别上没有翻译。但是,需要了解芯片组如何执行指令,尤其是那些可以并行执行指令的指令。
从C到汇编的转换非常“浅”,几乎一对一,但是可读性更高。但是,由于使用了标准库来提高可移植性,因此它上面有很多层。编译器不需要太多的工作来获得汇编代码,并且通常存在更强的优化以进行机器特定的更改。
C ++添加了更丰富的语言。但是,由于该语言增加了太多的复杂性,因此编译器很难为平台创建最佳代码。
然后我们转到秤的另一端。口译语言。这往往是最慢的,因为除了完成工作外,还花费一些时间来解析代码并将其转换为机器调用。
然后,我们将它们夹在中间。通常,它们具有针对平台优化的虚拟机层。然后编译器将创建代码供虚拟机执行。有时,这会像perl或pascal或ruby或Python一样同时发生。或像java这样的几个阶段。
其中一些虚拟机添加了JIT编译器的概念,它可以通过创建计算机级别的代码而不是转换中间字节代码来加快运行时间。
某些虚拟机级别较低,因此从字节码到机器码的转换较少。在保持可移植性的同时加快速度。
*p++=*q++;
许多机器上等效的机器代码比以前要快,array1[i]=array2[i];
但是在许多处理器上,情况恰恰相反,因此编译器可能最终将前一种代码样式转换为后者,这几乎是“浅”转换。
-O0
所做的任何优化。优化是使用编译器获得的好处,但是语言本身可以将几乎一对一的语言翻译为汇编语言。
还没有提到的一点是,在某些语言中,多次运行同一段代码将始终执行相同的操作序列;因此,计算机只需确定一次代码部分应该做什么。JavaScript的“严格使用”方言的主要好处之一是,一旦JavaScript引擎确定了一段代码的功能,它就可以在下次运行时利用该信息。没有“严格使用”,就不可能。
例如,在没有“ use strict”的情况下,一段代码如下:
function f() { return x; }
可以在立即调用上下文中返回变量X(如果有的话),或者可以在外部调用上下文中返回变量X,或者可以返回Undefined
。更糟糕的是,像这样的循环中:
for (i=0; i<40; i+=1) { g(i); }
JavaScript引擎无法知道g()
对此有何影响i
[或对其g
本身有什么影响。由于g
或i
可以完全合法地更改i
为字符串,因此JavaScript引擎不能在循环中简单地使用数字加法和数字比较,而是必须在每次循环中检查是否有函数调用对i
或进行了任何操作。g
。相比之下,在“严格使用”(比较合理)的方言中,JavaScipt引擎可以检查上面的代码,并知道每次循环都将使用相同的数字变量并调用相同的函数。因此,它仅需标识i
并起作用g
一次,而不是每次循环都要查找它们-节省大量时间。
好吧,这里有一些非常专业的答案,虽然这个答案与他们不太接近,但对您来说可能很直观。
您可能已经多次听到,当您需要尽快执行任务时,您将需要编写在汇编中执行该任务的代码。这是因为您仅执行完成任务所需的命令,仅此而已。虽然您可以使用高级语言来分几行实现此任务,但是编译器仍然需要将它们翻译为机器语言。由于您可以直接编写此翻译,因此它并不总是简约的。这意味着机器将花费许多时钟来执行您可以节省的命令。
尽管当今的编译器非常复杂,但它们仍然无法像最好的汇编程序员一样有效。
继续朝这个方向发展,这些不需要的命令的数量(通常)随着语言的高级化而增加。(并非所有高级语言都100%正确)
所以对我来说,如果对于某些代码,X的机器代码比Y的机器语言短(在运行时),X的语言要比Y的语言快。
很难确切地回答这个问题,因为它是如此复杂和多维(这几乎就像比较汽车品牌和其他标准一样),但是有新的科学研究,包括一个称为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很难被击败,但是在中等大小的输入上的性能差异不太明显,甚至使解释型语言也具有竞争力。与解释型或弱类型语言相比,编译型强类型语言在编译时可能会捕获更多缺陷,因此它们在运行时失败的可能性较小。我们讨论了这些结果对开发人员,语言设计师和教育工作者的影响。与解释型或弱类型语言相比,在编译时可以捕获更多缺陷的地方,运行时失败的可能性较小。我们讨论了这些结果对开发人员,语言设计师和教育工作者的影响。与解释型或弱类型语言相比,在编译时可以捕获更多缺陷的地方,运行时失败的可能性较小。我们讨论了这些结果对开发人员,语言设计师和教育工作者的影响。
计算机语言只是用于解释计算机操作的命令的抽象。
您甚至可以用计算机语言Python
编写并使用C编译器(cython)进行编译。
牢记这一点,无法比拟计算机语言的速度。
但是您可以在某种程度上比较同一语言的编译器。例如GNU C
编译器与Intel C
编译器。(搜索编译器基准)