我正在阅读解释语言的优缺点,最常见的缺点之一是速度慢,但为什么解释语言的程序很慢?
15 回答
本机程序使用为它们运行的处理器编写的指令运行。
口译语言就是“口译”。一些其他形式的指令由运行时读取和解释,运行时又执行本机机器指令。
这样想吧。如果您可以用您的母语与某人交谈,那通常比让口译员将您的语言翻译成其他语言以供听众理解的速度更快。
请注意,我上面所描述的是当一种语言在解释器中运行时。有许多语言的解释器,也有用于构建本机机器指令的本机链接器。速度降低(无论大小可能)仅适用于解释的上下文。
因此,说语言很慢是有点不正确的,而是它运行的上下文很慢。
C# 不是一种解释性语言,尽管它使用了一种中间语言 (IL),但它在执行之前被 JITted 到本机指令,所以它有一些相同的速度降低,但不是全部,但我敢打赌如果你为 C# 或 C++ 构建了一个成熟的解释器,它也会运行得更慢。
需要明确的是,当我说“慢”时,这当然是一个相对术语。
所有答案似乎都错过了这里真正重要的一点。这是如何实现“解释”代码的细节。
解释脚本语言较慢,因为它们的方法、对象和全局变量空间模型是动态的。在我看来,这是脚本语言的真正定义,而不是它被解释的事实。这需要在每次访问变量或方法调用时进行许多额外的哈希表查找。这也是为什么它们在多线程和使用 GIL(全局解释器锁)方面都很糟糕的主要原因。这种查找是花费大部分时间的地方。这是一个痛苦的随机内存查找,当你遇到 L1/L2 缓存未命中时真的很痛苦。
Google 的 Javascript Core8 非常快,并且针对简单优化的几乎 C 速度:他们将对象数据模型视为固定并创建内部代码来访问它,就像本机编译程序的数据结构一样。当添加或删除新变量或方法时,整个编译代码将被丢弃并再次编译。
该技术在 Deutsch/Schiffman 论文“Smalltalk-80 系统的有效实现”中得到了很好的解释。
为什么 php、python 和 ruby 不这样做的问题很容易回答:该技术实施起来极其复杂。
只有谷歌有钱购买 JavaScript,因为基于浏览器的快速 JavaScript 解释器是他们数十亿美元商业模式的基本需求。
将 interpeter 视为您碰巧没有的机器的模拟器
简短的回答是,编译语言是由机器指令执行的,而解释语言是由一个程序(用编译语言编写)执行的,该程序读取源代码或字节码,然后本质上模拟一个可以运行该程序的假设机器如果机器存在则直接。
将解释的运行时视为您目前实际上没有的机器的模拟器。
这显然被 Java、C# 和其他人所拥有的 JIT(即时)编译器复杂化了。理论上,它们与“AOT”(“一次性”)编译器一样好,但实际上这些语言运行速度较慢,并且由于需要让编译器在程序运行时耗尽内存和时间而受到限制。但是,如果您在这里说任何这些,请准备好吸引狂热的 JIT 捍卫者,他们坚持认为 JIT 和 AOT 之间没有理论上的区别。如果你问他们 Java 和 C# 是否与 C 和 C++ 一样快,那么他们就会开始找借口并稍微冷静下来。:-)
因此,C++ 完全适用于始终可以使用最大可用计算量的游戏。
在桌面和网络上,面向信息的任务通常由更抽象或至少编译更少的语言完成,因为计算机速度非常快,问题不是计算密集型的,所以我们可以花一些时间在目标上,比如 time-to -市场、程序员生产力、可靠的内存安全环境、动态模块化和其他强大的工具。
这是一个很好的问题,但在我看来应该有所不同,例如:“为什么解释语言比编译语言慢?”
我认为解释语言本身很慢是一个普遍的误解。解释语言并不慢,但根据用例,可能比编译版本慢。在大多数情况下,解释语言实际上已经足够快了!
“足够快”,再加上使用 Python 等语言提高生产力,例如,C 应该足以证明考虑解释型语言的理由。此外,如果您真的需要速度,您总是可以用快速的 C 实现替换解释程序的某些部分。但话又说回来,首先测量并确定速度是否真的是问题,然后优化。
除了其他答案还有优化:当您编译程序时,您通常不关心编译需要多长时间 - 编译器有很多时间来优化您的代码。当您解释代码时,它必须非常快地完成,因此可能无法进行一些更聪明的优化。
循环 a 100 次,循环的内容被解释 100 次为低级代码。
未缓存,未重用,未优化。
简单来说,编译器将一次解释为低级代码
编辑,评论后:
- JIT 是编译代码,而不是解释代码。它只是稍后编译而不是预先编译
- 我指的是经典定义,而不是现代的实际实现
一个简单的问题,没有任何真正简单的答案。底线是所有计算机真正“理解”的是二进制指令,这是像 C 这样的“快速”语言被编译成的。
然后是虚拟机,它们可以理解不同的二进制指令(如 Java 和 .NET),但必须通过 Just-In-Compiler (JIT) 即时将它们翻译成机器指令。这几乎一样快(在某些特定情况下甚至更快,因为 JIT 比静态编译器拥有更多关于如何使用代码的信息。)
然后是解释语言,它们通常也有自己的中间二进制指令,但是解释器的功能很像一个循环,其中有一个大的 switch 语句,每条指令都有一个案例,以及如何执行它。对底层机器代码的这种抽象级别很慢。涉及更多指令,解释器中的长链函数调用甚至可以做简单的事情,并且可以说内存和缓存没有得到有效使用。
但解释型语言的速度通常足以满足使用它们的目的。Web 应用程序总是受 IO(通常是数据库访问)的约束,这比任何解释器都慢一个数量级。
没有解释性语言这样的东西。任何语言都可以由解释器或编译器实现。如今,大多数语言都有使用编译器的实现。
也就是说,解释器通常较慢,因为他们需要在运行时处理语言或与之相当接近的东西并将其翻译成机器指令。编译器只将这种转换为机器指令一次,然后直接执行它们。
是的,解释语言很慢......
但是,请考虑以下事项。我有一个问题要解决。我用 Python 解决问题花了 4 分钟,程序运行用了 0.15 秒。然后我尝试用 C 写,运行时间为 0.12 秒,我用了 1 个小时才写完。这一切都是因为解决问题的实际方法是使用哈希表,而哈希表无论如何都主导了运行时。
解释型语言需要在执行时读取和解释您的源代码。对于已编译的代码,很多解释都是提前完成的(在编译时)。
如今,很少有当代脚本语言被“解释”;它们通常被即时编译成机器代码或某种中间字节码语言,后者(更有效地)在虚拟机中执行。
话虽如此,它们变慢了,因为您的 cpu 在每个“代码行”中执行更多指令,因为许多指令都用于理解代码而不是执行该行的语义所暗示的任何事情!
阅读此解释语言的优点和缺点
这是该帖子中与您的问题相关的想法。
解释器的执行通常比常规程序执行效率低得多。发生这种情况是因为每条指令都应该在运行时传递解释,或者在较新的实现中,代码必须在每次执行之前编译为中间表示。
出于同样的原因,通过翻译器交谈比使用母语交谈要慢。或者,用字典阅读。翻译需要时间。
更新:不,我没有看到我的答案在一定程度上与接受的答案相同;-)
解释代码比运行编译代码慢,因为解释器必须在每次执行程序时分析程序中的每个语句,然后执行所需的操作,而编译代码只是在编译确定的固定上下文中执行操作。这种运行时分析称为“解释开销”。在解释器中访问变量也较慢,因为标识符到存储位置的映射必须在运行时而不是在编译时重复完成。
请参阅此IBM 文档,
解释的程序每次执行都必须翻译,有较高的开销。因此,解释语言通常比预定义请求更适合临时请求。
在 Java 中,虽然它被认为是一种解释型语言,但它使用JIT(即时)编译,通过使用缓存技术来缓存已编译的字节码来缓解上述问题。
JIT 编译器读取许多部分(或完整,很少)的字节码,并将它们动态编译成机器代码,以便程序运行得更快。这可以在每个文件、每个函数甚至任意代码片段上完成;代码可以在即将执行时进行编译(因此称为“即时”),然后缓存并在以后重复使用,而无需重新编译。