我们能否就解释代码和编译代码的性能做出一般性陈述?


60

我正在比较两种技术,以便提出建议,公司应该使用其中的一种。技术A的代码被解释,而技术B的代码被编译为机器代码。在我的比较中,我指出技术B一般而言会具有更好的性能,因为它没有解释过程的额外开销。我还指出,由于程序可以用多种方式编写,因此用技术A编写的程序仍然有可能胜过使用技术B编写的程序。

当我将此报告提交审核时,审核员表示我没有提供清楚的理由说明为什么解释流程的总费用通常会足够大,以至于我们可以得出结论,技术B的性能会更好。

所以我的问题是,我们能否谈谈编译/解释技术的性能?如果我们可以说编译的速度通常快于解释的速度,那么我该如何说服审阅者呢?


76
由于这似乎是一个实际问题,而不是学术练习,因此建议甚至不要尝试给出一般性答案,而是实际评估技术A和B。虽然可能无法给出一般性答案,但是肯定有可能评估两种特定技术的性能特征,指出它们与您的组织感兴趣的应用程序类型相关
。– 5gon12eder

26
这个问题询问有关通用性的问题,但是看来您真正的问题在于技术A和B的特性。虽然我认为总体上来说解释性语言可能会比较慢,但是这一事实可能与您的特定技术完全没有关系。无论总体趋势如何,特定的解释后的B很有可能比编译后的A快。
Bryan Oakley

18
随机选择一种解释语言和一种编译后的语言,然后下注一美元,认为编译后的语言会更快。重复足够的时间,您最终将走得足够远,可以在Subway购买午餐。但是,有能力的程序员可以通过更快,更有趣的方式赚到这么多钱。而且Subway并不是那么出色。
Ed Plunkett

23
你似乎在矛盾自己。一方面,您想对解释型语言和编译型语言进行一般性说明。但是,另一方面,您希望将该一般性声明应用于具体方案。但是,一旦将其应用于具体场景,就不会再泛泛了。因此,即使您可以确定一般情况下解释语言的速度较慢,您的审阅者也不会在意。您正在分析两种非常具体的技术。从字面上看,这与概括相反。
loneboat

8
老实说,为什么您要针对基于性能的两种首要技术中的一种提出公司相关的建议?在特殊情况下(例如3D高速游戏编程),性能可能是一个相关标准,但是对于大多数实际业务程序而言,它应该是您比较的最后一件事,而不是第一件事。
布朗

Answers:


111

没有。

通常,语言实现的性能主要取决于在其上花费的金钱,资源,人力,研究,工程和开发量。

特别是,特定程序的性能主要取决于其算法中的思考量。

有一些非常快速的解释器,有些编译器生成非常慢的代码。

例如,Forth仍然流行的原因之一是,在许多情况下,解释的Forth程序要比等效的编译C程序快,而与此同时,用Forth编写的用户程序加上编写的Forth解释器用C语言编写的程序比用C语言编写的用户程序


12
据我可以告诉你自己先回答一个链接(可能是重复的)问题涉及这些问题比这好得多
蚊蚋

11
如果不可能就性能做出一般性结论,我们可以用A编写一个比B中的类似程序更好的程序,但是我们也可以用B编写的优于A编写的程序。我们不能真正得出任何有关那时的语言速度如何?无论如何,Forth看起来都很有趣,我稍后将不得不阅读更多内容。
EpicSam'1

36
@EpicSam:正确。“语言的速度”这个想法根本上是荒谬的。
约尔格W¯¯米塔格

23
一般而言:具体。
igouy

19
我假设“ ...和一些非常慢的编译器”是指它们生成的代码,而不是它们的编译速度。
martineau

81

概括和特定方案实际上是相反的。

你似乎在矛盾自己。一方面,您想对解释型语言和编译型语言进行一般性说明。但是,另一方面,您希望将该一般说明应用于涉及技术A和技术B的具体方案。

一旦将某些东西应用于具体场景,就不再泛化了。因此,即使您可以得出解释性语言总体上较慢的情况,也仍然无法说明问题。您的审阅者不在乎泛化。您正在分析两种非常具体的技术。从字面上看,这与概括相反。


3
相对于问题标题,这是迄今为止对问题文本的最佳答案。
David Moles

37

根据经验,与使用解释程序的宿主语言编写程序相比,解释程序的速度要慢2到10倍,而对于更多动态语言的解释程序则要慢。这是因为解释后的程序必须完成所有实际工作,但是另外还有解释上的开销。

根据解释器的结构,可能会有非常明显的差异。解释器设计有两个相互矛盾的流派:一个说操作码应尽可能小,以便它们可以更容易地进行优化;另一个说,操作码应尽可能大,以便我们在解释器中做更多的工作。当程序的结构符合解释器的原理时,开销可以忽略不计。

例如,Perl是一种面向文本操作的解释语言。惯用的Perl程序执行文本操作不会比C程序慢很多,甚至在某些情况下甚至可能胜过C程序(可能是因为Perl使用不同的字符串表示形式,并且内置了各种与文本和IO相关的优化)。但是,在Perl中进行数字运算将非常缓慢。增量++x是单个汇编指令,但是涉及Perl解释器的多个指针遍历和分支。我最近将一个CPU绑定的Perl脚本移植到了C ++,并获得了7到20倍的加速,具体取决于编译器的优化级别。

在这里谈论优化很重要,因为经过优化的优化解释器可能会在性能上优于非优化的天真的编译器。由于创建优化的编译器很困难并且需要大量的工作,因此“技术B”不太可能具有这种成熟度。

(注意:“ 计算机语言基准测试”网站的结构令人困惑,但是一旦您遇到了一个问题的时间表,您就会注意到各种语言的性能无处不在–通常,性能界限不明确该网站最重要的部分不是基准测试结果,而是有关有意义的基准测试有多困难的讨论。)

选择技术时,语言运行时本身的性能完全不相关。技术必须满足一些基线限制(我们的预算为$ x,我们必须能够在yyyy-mm-dd之前交付,我们必须满足各种非功能性要求),这一点很重要,并且它的价格较低总拥有成本(包括开发人员生产力,硬件成本,业务机会成本,错误风险和技术意外约束,维护成本,培训和雇用成本等)。例如,在上市时间是最重要的因素的行业中,具有最佳开发人员生产力的技术将是最合适的。对于大型组织而言,可维护性和长期成本可能更有趣。


10
如果您认为“计算机语言基准测试游戏网站的结构令人困惑”,请在支持您观点的特定页面上提供一个URL,而不是期望人们从顶层进行搜索以寻找他们可能永远找不到的内容!节目; 不要只是告诉。
igouy

8
如果您认为“该网站最重要的部分不是基准测试结果,而是有关有意义的基准测试有多难的讨论”,那么请为这些页面提供URL。节目; 不要只是告诉。
igouy

4
这将为那些阅读您的答案的人带来方便。(我只是管理基准游戏的人)。
igouy

2
@amon将答案中的k核苷酸示例链接起来,将使其更具可读性,并且注释也变得有用,就像链接讨论一样(无需阅读整个站点,对我来说您正在谈论的讨论对我来说并不明显)。
David Moles

1
您是从哪里获得2到10倍的收益?该比率完全取决于每个字节码的获取和分派到处理程序所花的时间,而不是每个处理程序执行所花的时间,并且只有在获取周期花的时间是处理程序的9倍时,才可能有10倍的可能。不可能。通常,执行由处理程序主导。并且获取周期几乎可以忽略不计。
user207421'1

18

您绝对可以说出有关编译/解释技术的性能。但是首先,您必须定义“性能”。如果您要构建一个计算简单的嵌入式系统,则“性能”可能会偏向于内存使用方面。由于在JVM或.NET中的内存开销可以忽略不计,因此在大型数据集上运行的计算复杂的系统会发现自己在每单位时间的计算数量中定义了“性能”。

一旦确定了“性能”是什么,就可以说“在任何给定时间我们将有500亿个对象在内存中,并且解释后的techA为每个对象增加了8个字节用于内部管理,这相当于400 GB的内存开销与不添加此数据的techB相比”


12

这是一个技术问题,您已经获得了很多很好的技术答案,但是我想指出您所处情况的一个稍有不同的方面:您不能仅仅基于“技术A或技术B”这样的决定基于技术和/或性能原因。

诸如此类的技术方面只是A和B之间决策的一小部分。还有许多其他因素需要牢记:

  • 是否涉及任何许可费用?例如:与使用PostgreSQL计算机群集相比,使用SQL Server计算机群集必须支付(大量费用)。
  • 我是否有熟悉该技术(堆栈)及其生态系统的员工?如果是,它们可用吗?如果没有,我可以雇用一些吗?我要花多少钱?还是我训练现有的?那要花我多少钱?
  • 客户想要什么?很多时候这可能是一个问题。
  • 我推荐的技术准备好用于生产了吗?还是仅仅是目前的炒作可能会消失?(例如,想想Node.js刚问世的时候)
  • 我推荐的技术是否与现有架构或我所考虑的架构完全吻合?还是我需要使它们无缝地协同工作来花费很多钱?
  • 以及许多其他方面,具体取决于您的具体情况。

如您所见,做出这样的决定时需要考虑很多东西。

我知道这并不能具体回答您的问题,但我认为它可以使您对自己的情况和决策的细节有更全面的了解。


10

部分评估是与相关解释器和编译器相关的概念框架。

我们能否就解释代码和编译代码的性能做出一般性陈述?

编程语言是规范(写在某些报告中,例如R5RSn1570)。它们不是软件,因此谈论性能甚至没有任何意义。但是某些编程语言可能具有多种实现,包括解释器编译器

即使在像C 这样的传统编译语言(即,其实现通常是编译器的语言)中,也经常会解释某些部分。例如,printf的格式控制字符串(在C标准中定义)通常是“解释”的(由C标准库提供,该具有使用可变参数技术的printf 功能),但是某些编译器(包括GCC)能够-在有限的特定范围内用例-对其进行优化并将其“编译”为较低级别的调用。

甚至在“解释器”内部,某些实现也使用JIT编译技术(因此在运行时生成机器代码)。一个很好的例子是luajit。其他实现(例如Python,Ocaml,Java,Parrot,Lua)将源代码转换为字节码,然后对其进行解释。

SBCL是Common Lisp的“编译器”,可以将每个REPL交互(以及对evaletc的调用等)动态地转换为机器代码。因此,您认为它是翻译。浏览器中的大多数JavaScript实现(例如v8)都使用JIT编译技术。

换句话说,解释器和编译器之间的区别非常模糊(实际上两者之间是连续的),实际上,大多数编程语言实现通常都具有解释器和编译器(至少在字节码方面)。

独立于使用大多数“编译器”或“解释器”之类的技术,实现可以快速或缓慢。

一些语言特征倾向于解释方法(并且只能通过整个程序分析来有效地编译)。

对于某些类型的问题,使用某些元编程方法设计软件是值得的,并且可以大大提高速度。您可以想象,给定一些特定的输入,您的程序会动态生成专门的代码来对其进行处理。甚至可以使用C或C ++(使用某些JIT库或生成一些C代码并将其编译为可动态加载的插件)来实现。

另见本相关的关于Python的问题,


7

对于像这样的代码A = A + B,它可以编译为一两个机器指令,每个指令要花费一定的周期。出于简单的原因,没有解释器可以在该数量的循环中执行相同的操作。

解释器还执行自己的指令集(称其为字节码,p码,中间语言等)。每次看到类似ADD的字节码时,都必须以某种方式查找它,然后跳转到执行加法的代码。

接下来它看到它的时候,它必须重复那个查询,除非它有一个方法来记住事先查询。如果它确实可以记住以前的查找,则不再是我们所说的“解释器”,而是即时编译器或JITter。

另一方面...

对于类似的代码callSomeFunction( ... some args ...),在输入该代码和离开该代码之间要花费多少周期?这一切都取决于内部发生了什么callSomeFunction。即使callSomeFunction它本身是编译的,也可能是几个,甚至可能是数万亿。如果很多,那么讨论该行代码的解释成本毫无意义-钱就在别处。

请记住,解释型语言具有其自身的价值,例如,无需编译它们。(将表面语法“编译”为字节码需要花费很短的时间。例如以R或MATLAB为例。)

此外,智能编程级别还需要灵活性。在Minsky的“心灵社会”的第6.4章B-大脑中,有A程序与世界打交道,有B程序与A程序打交道,并且可以有更高的层次。编写和管理其他程序的程序可以在解释性系统中更轻松地完成。

在Lisp中,您可以编写(+ A B)添加A和B的内容,但是一旦编写完成,您只能选择是否运行它。您还可以编写(eval (list '+ 'A 'B))构造程序然后执行的程序。它可以构造一些不同的东西。

该程序的主题是另一个程序。这更容易用解释性语言编写(尽管正如Jörg所指出的,Lisp的较新版本虽然可以eval即时编译,所以它们没有解释速度上的损失)。


1
我觉得有趣的是,您说用解释语言编写元级程序更容易,但是使用Lisp作为示例,其中编译了大多数实现。
约尔格W¯¯米塔格

1
@JörgWMittag:当然,但他们都有evalapply功能,这是翻译。
Mike Dunlavey

2
我很确定至少在SBCL eval上没有解释。而且也不是apply。当然,有些实现包含解释器,但SBCL没有。
约尔格W¯¯米塔格

1
解释器可以在运行时优化循环条件,并压缩剩余的迭代。这在编译程序中很少出现。具体来说,Oracle的Hotspot正是这样做的。
Basilevs

2
@JörgWMittag:当然eval没有解释ed。这是一个解释
Mike Dunlavey

5

某种程度上,这取决于但一般而言,编译后的环境(通过JIT还是静态编译的环境)对于许多计算密集型任务来说会更快(假设为了简单起见,使用相同的语言)。

部分原因是解释语言需要具有解释器循环-循环用于读取指令,选择适当的操作并执行它。在最好的情况下,例如解释Python或Java字节码(就像旧的 JVM一样),它的开销很少,并且对分支预测器造成了严重破坏-如果没有最后一个预测器,您可能会因预测错误而受到巨大的惩罚。即使是非常笨拙的JIT也可以显着加快速度。

那就是说翻译的语言可能会作弊。例如,Matlab为矩阵乘法优化了例程,只需进行少量更改就可以使代码在GPU上运行(免责声明:我在nVidia工作-这里表达的任何观点都是我的,并不代表雇主的观点)。这样,您就可以编写简短而强大的高级代码,而不必担心细节-有人确实很在意它,并花费时间和资源来用低级语言进行优化。它没有继承任何东西,并且也不能阻止,例如,用Matlab来使代码JIT,但是通常没有理由,因为与低级例程相比,调用高级例程的开销很小。

TL; DR-编译后的程序相对于解释后的程序具有巨大的性能优势(有关AppleApple的比较,请参阅PyPy Speed)。但是,可执行文件的速度只是问题的一部分,并且可能不会对整体速度产生很大的影响(如果时间主要花费在库中)。实施也很重要。


5

您的假设是有根据的,尽管这是一个假设。

我不会讲究为什么编译后的代码应该比解释后的代码更快的原因:如果您知道计算机的工作方式,这将是显而易见的。对于某些类型的问题,差异可能是数量级。如果您的审稿人对该一般案件提出严重异议,他们将不知道自己在说什么。

但是,他们可能要指出的是,所开发的应用程序类型之间的差异是否显着。如果它主要是I / O或主要是调用编译的库,并且没有太多的计算量,则解释过程的开销确实可以忽略不计。

但是我的帖子的重点是:作为IT专家,您经常会被要求根据有关事物应该如何运作的一般知识来做出快速决策。进行特定的测试可能会为您提供更准确的答案,但是这会花费更多的钱,而且您不会先到达那里。

但是有时您会被吸引住。这是发生在我身上。您做了一个很好的假设,然后发现您没有考虑到世界的愚蠢。

但是我无法像我一直以来最喜欢的迪尔伯特漫画那样解释。没有什么比这更聪明的危险了。

替代文字

TL; DR:您应该是对的,但请检查现实情况,以防万一。


3

除非您使用某种异国情调的东西,否则您的问题将不会与解释语言A和编译语言B的性能有关。

因为如果您/您的团队了解A,而不是B,因此用A编写的代码要比B好,那么您在A上的性能可能会比B更好。如果您有使用一种语言的经验,并且该语言/图书馆可以您需要的工作,坚持下去。

这是各种语言的正则表达式链接;您会发现无论是否编译,都可以用某种语言更好地实现正则表达式:http : //benchmarksgame.alioth.debian.org/u64q/performance.php?test=regexdna


问题在于,团队可以同时使用A和B,并且在我要求他们输入时没有表示偏爱其中任何一个。
EpicSam '17

@EpicSam那么他们过去的项目呢?
Walfrat

1
A和B都已使用。但是,他们希望对所有项目都使用1种技术。两种技术的性能都足以满足当前项目的需要。但是,在寻找潜在的未来项目时,应考虑其中之一的潜在更高性能。
EpicSam'1

3
@EpicSam可以更好地寻找有关该语言的社区以及可用于帮助您进行项目的库/框架。
Walfrat

6
我同意@Walfrat。我敢打赌,“潜力最大”的语言是直接汇编或一些原始的CPU指令集。但是,我们之所以谈论这些语言,是因为“显而易见”,拥有诸如编译器,解释器和预先编写的库之类的工具至关重要。我认为工具/社区知识的可用性比解释/编译之间的选择更为重要
Ivan

1

我认为仅基于一种技术已被编译而另一种已被解释的事实来谈论两种技术的性能并不是一个好主意。如其他答案所述,它可能取决于应用程序的领域(某些语言可能经过优化,可以非常快速地执行某些操作,而更慢地执行其他操作),以及将要使用该技术的人员的经验。

我认为,如果您采用了一些优秀的口译语言编码器,并为他们提供了一些他们不熟悉的技术,那么您可以期望获得性能上的提高,这是不合理的。也许从理论上讲,后者可能会带来更好的性能,但是实际上,没有必要的技能和经验,您将不会利用所有优化机会。

我还从一位著名的硅谷公司员工那里听说,他们喜欢使用更简单的语言,因为付钱给一些熟练的开发人员来维护复杂但高度优化的代码不仅成本高昂而且麻烦。购买更多的钻机以应对效率较低的实施,因此在选择技术时也应考虑到这一点。


0

一次,我不得不做出类似的详尽声明来证明一个重大决定。

首先,他们可能不想相信一个不起眼的工程师,因此我找到了一些可比较的基准测试并引用了它们。其中有很多人来自Microsoft等知名大学。他们会说:“方法A比方法B快3到10倍,具体取决于变量X和Y。

其次,您可能想运行自己的基准测试,也许使用有问题的代表性代码块,或者已经拥有的类似代码。隔夜运行1000次,因此确实存在可测量的差异。

在这一点上,A和B之间的差异(或没有差异)应该非常清楚,以至于您只需要介绍一下即可。因此,应清楚地格式化结果,并在可能的情况下使用图表说明所有假设并定义所有使用的数据。


1
做我自己的基准测试的问题是,我实际上只是对两个用A和B编写的特定程序进行基准测试,而不是整个A和B。应该有可能在A和B中创建解决问题X的程序,其中A更快,然后以B更快的方式重写它们,反之亦然。从本质上讲,这可以使您从结论中进行追溯,例如,如果您更喜欢A,则可以选择A更快或更简单的方案来优化A版本,直到胜过B中的版本。因此,我们只能得出特定条件下的性能情况不一般。
EpicSam'1

根据此决定的大小和重要性,您可以同时使用A和B来实现功能的代表性部分。如果这确实是一个重大决定,那么这不会浪费时间。您必须证明自己的部门具有代表性,并且不要试图偏personal您的个人喜好。
RedSonja

1
@EpicSam找到一个明显喜欢A的人,并让他们优化A的基准。对B进行相同的操作。您只需要确保两个程序员的水平大致相同,并花费相同的时间即可。选择基准仍然存在问题,但是要让两个程序员都参与决策。理想情况下,让他们就基准达成一致。另一个问题是时间的浪费,但这可以通过选择简单有用的方法来解决。
maaartinus

0

我认为任何动态语言都比静态编译语言有优势:“运行时优化”

这就是Java可以比C ++更快的原因之一

是的,加载动态类型的语言将始终带来翻译成本,并且处于不利地位。但是一旦运行,解释器就可以使用静态语言永远不会拥有的运行时信息来分析和增强常用的代码路径

注意:Java是一种解释性语言,而不是动态语言。但这是可以加速运行时信息的一个很好的例子


-3

...我还指出,由于可以以多种方式编写程序,因此用技术A编写的程序仍然有可能超过技术B编写的程序。

当我将此报告提交审核时,审核员表示我没有提供清楚的理由说明为什么解释流程的总费用通常会足够大,以至于我们可以得出结论,技术B的性能会更好。...

这是我的方法:

通常,解释器是编译的,因此,如果从较低的角度看,每种解释技术都不过是编译技术。因此,如果您很聪明(通常就是这样),那么编译技术就会越来越多,并且有更多的可能性,您永远不会恶化。这取决于编译时可用的信息量以及仅在运行时可获得的信息量以及编译器和解释器的性能如何,但是从理论上讲,总有可能至少使任何解释器的性能与合适的编译器相等,只是因为解释器是由编译器制造的。这是可能的,但这并不意味着技术A和B都是如此。

在实践中,只需告诉审阅者所有可比较编译和解释系统的基准。然后请他建议一个比您优化的程序集编码特定算法更好的解释器。

也许应该补充一点,在比较两个特定的技术A和B时,任何这样的一般性声明都根本没有帮助。那里的A和B的选择比解释或编译它们重要得多。


2
完全错误。您不了解解释器如何工作以及编译器如何工作。
rghome
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.