为什么口译语言会变慢?

时间:2009-11-07 21:03:04

标签: performance interpreted-language

我正在阅读解释性语言的优点和缺点,其中一个最常见的缺点是速度慢,但为什么解释语言中的程序会变慢?

15 个答案:

答案 0 :(得分:56)

本机程序使用为其运行的处理器编写的指令运行。

解释语言就是“解释”。其他形式的指令由运行时读取和解释,运行时又执行本机机器指令。

这样想。如果您可以用自己的母语与某人交谈,那通常比让翻译人员将您的语言翻译成其他语言以便听众理解更快。

请注意,我上面描述的是在语言在解释器中运行时。有许多语言的解释器,还有用于构建本机机器指令的本机链接器。速度降低(但可能的大小)仅适用于解释的上下文。

因此,说语言很慢,而不是它运行的上下文很慢,这有点不正确。

C#不是一种解释型语言,即使它使用的是中间语言(IL),在执行之前它也会被本机指令JIT,所以它有一些相同的速度降低,但不是所有这一切,但我敢打赌,如果你为C#或C ++构建一个完全成熟的解释器,它也会运行得更慢。

而且要明确的是,当我说“慢”时,这当然是一个相对的术语。

答案 1 :(得分:17)

所有答案似乎都错过了这里真正重要的一点。这是详细说明“解释”代码的实现方式。

解释的脚本语言较慢,因为它们的方法,对象和全局变量空间模型是动态的。在我看来,这是脚本语言的真正定义,而不是它被解释的事实。这需要在每次访问变量或方法调用时进行许多额外的哈希表查找。它的主要原因是它们在多线程和使用GIL(全局解释器锁)时都很糟糕。这种查找是花费大部分时间的地方。这是一个痛苦的随机内存查找,当你得到L1 / L2缓存未命中时会非常痛苦。

谷歌的Javascript Core8速度非常快,几乎可以通过C速度进行简单的优化:它们将对象数据模型固定下来并创建内部代码来访问它,就像本机编译程序的数据结构一样。添加或删除新变量或方法时,将丢弃并重新编译整个编译代码。

该技术在Deutsch / Schiffman论文“Smalltalk-80系统的有效实现”中得到了很好的解释。

为什么php,python和ruby没有这样做的问题很简单:这个技术实现起来非常复杂。

只有谷歌有钱支付JavaScript,因为基于浏览器的快速JavaScript解释器是他们十亿美元商业模式的基本需求。

答案 2 :(得分:8)

将interpeter视为您没有碰巧的机器的模拟器

简短的回答是编译语言是由机器指令执行的,而解释的语言是由程序(用编译语言编写)执行的,该程序读取源代码或字节码,然后基本上模拟一个假设的机器如果机器存在,会直接运行程序。

将解释后的运行时视为您当前没有实际拥有的计算机的模拟器。

Java,C#等人拥有的JIT(Just In Time)编译器显然很复杂。从理论上讲,它们与“AOT”(“一次性”)编译器一样好,但在实践中,这些语言运行速度较慢,并且需要让编译器在程序的运行时使用内存和时间。但是,如果你说在这里的任何一个准备好吸引狂热的JIT防守者,他们坚持认为JIT和AOT之间没有理论上的区别。如果你问他们Java和C#是否和C和C ++一样快,那么他们就会开始找借口并稍稍冷静下来。 : - )

因此,C ++完全适用于可以随时使用最大可用计算量的游戏。

在桌面和Web上,面向信息的任务通常由具有更多抽象或至少更少编译的语言完成,因为计算机速度非常快且问题不是计算密集型的,因此我们可以花一些时间在像上市时间,程序员生产力,可靠的内存安全环境,动态模块化和其他强大的工具。

答案 3 :(得分:7)

这是一个很好的问题,但在我看来应该有所不同,例如:“为什么解释语言比编译语言慢?”

我认为解释性语言本身很慢是一种常见的误解。解释语言不慢,但根据用例,可能比编译版本。在大多数情况下,解释语言实际上足够快

“足够快”,加上使用像Python这样的语言的生产力提高,例如,C应该足以考虑解释性语言。此外,如果您真的需要速度,您可以使用快速C实现替换解释程序的某些部分。但话又说回来,首先测量并确定速度是否真的是问题,然后进行优化。

答案 4 :(得分:4)

循环100次,循环内容被解释为100次到低级代码。

未缓存,未重用,未优化。

简单来说,编译器会将一次解释为低级代码

评论后编辑:

  • JIT is compiled code,未解释。它刚刚编译,而不是前期
  • 我指的是经典定义,而不是现代实际实现

答案 5 :(得分:3)

除了其他答案之外还有优化:当你编译程序时,你通常不关心编译需要多长时间 - 编译器有很多时间来优化你的代码。当您解释代码时,必须非常快速地完成,因此可能无法进行一些更聪明的优化。

答案 6 :(得分:2)

一个简单的问题,没有任何真正简单的答案。最重要的是,所有计算机真正“理解”的是二进制指令,这就是编译C语言的“快速”语言。

然后有虚拟机,它们可以理解不同的二进制指令(如Java和.NET),但必须由Just-In-Compiler(JIT)即时翻译成机器指令。这几乎同样快(在某些特定情况下甚至更快,因为JIT在静态编译器方面的信息比使用代码的方式更多。)

然后是解释语言,它们通常也有自己的中间二进制指令,但是解释器的功能很像一个带有大型switch语句的循环,每个指令都有一个case,以及如何执行它。对底层机器代码的这种抽象级别很慢。涉及到更多的指令,解释器中的长链函数调用甚至可以执行简单的操作,并且可以认为内存和高速缓存的使用效果不是很好。

但解释性语言通常足够快,以达到使用它们的目的。 Web应用程序总是受IO(通常是数据库访问)的约束,这比任何解释器都慢一个数量级。

答案 7 :(得分:1)

没有解释性语言这样的东西。任何语言都可以由解释器或编译器实现。目前,大多数语言都使用编译器进行实现。

也就是说,解释器通常较慢,因为它们需要在运行时处理语言或与其相近的语言,并将其转换为机器指令。编译器只对机器指令执行一次转换,然后直接执行。

答案 8 :(得分:0)

来自about.com

  

处理解释语言   在运行时。每行都读,   分析并执行。不得不   每次循环重新处理一行   是什么使解释语言如此   慢。这个开销意味着   解释代码运行在5到10之间   比编译代码慢一倍。该   解释语言如Basic或   JavaScript是最慢的。其   优点不是必须的   更改后重新编译,即   你正在学习编程时很方便。

然而,对于Java和C#等语言来说,慢5-10倍并不一定如此。它们被解释,但just-in-time compilers可以为某些操作生成机器语言指令,从而大大加快速度(有时接近编译语言的速度)。

答案 9 :(得分:0)

解释语言需要在执行时读取和解释您的源代码。使用已编译的代码,很多解释都会提前完成(在编译时)。

答案 10 :(得分:0)

现在很少有当代脚本语言 “被解释”;它们通常是动态编译的,可以是机器代码,也可以是某种中间字节码语言,可以(更有效地)在虚拟机中执行。

话虽如此,它们的速度较慢,因为你的cpu每个“代码行”都执行了更多的指令,因为许多指令都花在理解代码上,而不是做任何线条的语义建议!

答案 11 :(得分:0)

阅读此Pros And Cons Of Interpreted Languages

这是该帖子中与您的问题相关的想法。

  

口译员的执行是   通常效率低得多   正常的程序执行。它发生了   因为要么每一条指令   应该通过解释   运行时或更新的   实现,代码必须是   编译成中间人   每次执行前的表示。

答案 12 :(得分:0)

出于同样的原因,通过翻译器讲话比使用母语更慢。或者,用字典阅读。翻译需要时间。

更新:不,我没有看到我的答案与已接受的答案相同,在某种程度上; - )

答案 13 :(得分:0)

是的,解释语言很慢......

但是,请考虑以下事项。我有一个问题需要解决。我花了4分钟来解决Python中的问题,程序耗时0.15秒。然后我尝试在C中编写它,我得到了0.12秒的运行时间,我花了1个小时来编写它。所有这一切都是因为解决问题的实际方法是使用哈希表,而哈希表无论如何都主导了运行时。

答案 14 :(得分:0)

Wikipedia says

  

解释代码比运行编译代码慢,因为解释器必须在每次执行时分析程序中的每个语句,然后执行所需的操作,而编译的代码只是在确定的固定上下文中执行操作通过汇编。此运行时分析称为“解释开销”。在解释器中访问变量的速度也较慢,因为标识符到存储位置的映射必须在运行时而不是在编译时重复进行。

请参阅此IBM doc

  

解释程序每次执行时都必须翻译,有更高的开销。因此,解释语言通常比预定义请求更适合于临时请求。

在Java中,虽然它被认为是一种解释型语言,但它使用JIT(即时)编译,通过使用缓存技术缓存已编译的字节码来缓解上述问题。

  

JIT编译器在许多部分(或完整,很少)读取字节码,并将它们动态编译为机器代码,以便程序可以更快地运行。这可以按文件,按功能或甚至任意代码片段完成;代码可以在即将执行时编译(因此名称为“just-in-time”),然后在不需要重新编译的情况下进行缓存和重用。