编译和解释有什么区别?

时间:2014-06-19 12:40:53

标签: compiler-construction compilation interpreter interpretation

我刚与一位同事进行了对话,并谈论了V8 JavaScript引擎。根据维基百科,

  

V8在执行之前将JavaScript编译为本机机器代码,而不是更传统的技术,例如解释字节码或将整个程序编译为机器代码并从文件系统执行它。

其中(如果我错了,请纠正我)" 解释字节码"是Java的工作方式," 编译整个程序"适用于C或C ++等语言。现在我们想知道,辩论并提出关于差异,相似性的错误断言和推定。为了结束这一点,我建议问问专家。

那么,谁能够

  1. 命名,解释和/或引用所有主要方法(例如预编译与运行时解释)
  2. 可视化或提供关于来源,编辑和解释之间关系的方案
  3. 为#1。
  4. 的主要方法提供示例(名称编程语言)

    注意:

    • 我不是在寻找关于不同范式的长篇散文,而是一个视觉支持的快速概述。
    • 我知道Stackoverflow并不打算成为程序员的百科全书(而是针对更具体问题的Q& A平台)。但是,由于我可以找到很多热门问题,这类问题为某些主题提供了百科全书式的观点(例如[1][2][3][4],{{3我启动了这个问题。
    • 如果此问题更适合任何其他StackExchange网站(例如[5]),请让我知道或标记此问题以便审核。

2 个答案:

答案 0 :(得分:13)

由于一个简单的原因,几乎不可能回答你的问题:没有一些方法,它们是一个连续统一体。这个连续体中涉及的实际代码也是完全相同的,唯一的区别在于事情发生时,以及中间步骤是否以某种方式保存。这个连续体中的各个点(不是一条线,一条渐进线,而是一条可以靠近的不同角落的矩形):

  1. 阅读代码
  2. 了解代码
  3. 执行您理解的内容
  4. 沿路缓存各种中间数据,甚至将它们永久保存到磁盘上。
  5. 例如,纯粹的解释编程语言几乎没有做#4和#2有点隐含地发生在1到3之间,所以你几乎没有注意到它。它只是读取代码的各个部分,并立即对它们做出反应。这意味着实际开始执行的开销很低,但是在一个循环中,相同的文本行被读取并重新读取。

    Diagram of the balance of an Interpreter (not much caching going on)

    在矩形的另一个角落,传统上有编译的语言,通常,第4项包含将实际机器代码永久保存到文件中,然后可以在以后运行。这意味着你在开始时等待相当长的时间直到整个程序被翻译(即使你只是在其中调用单个函数),但OTOH循环更快,因为源不需要是再读一遍。

    Diagram of the balance of a Compiler (mostly caching)

    然后介于两者之间,例如: 虚拟机:为了便于携带,许多编程语言不能编译为实际的机器代码,而是编译为字节代码。然后有一个编译器生成字节代码,以及一个解释器,它接受这个字节码并实际运行它(有效地#34;将其转换为机器代码")。虽然这通常比编译并直接转到机器代码要慢,但是将这种语言移植到另一个平台更容易,因为您只需要移植字节码解释器,这通常是用高级语言编写的,这意味着你可以使用现有的编译器执行此操作"有效转换为机器代码",并且不必为要运行的每个平台制作和维护后端。此外,如果您可以执行一次编译到字节码,然后只分发编译的字节码,这样可以更快,这样其他人就不必花费CPU周期。在代码上运行优化器,只需支付字节码到本机的翻译费用,这在您的使用案例中可以忽略不计。此外,您还没有分发您的源代码。

    介于两者之间的另一件事是即时编译器(JIT),它实际上是一个解释器,它以编译的形式保存它运行过一次的代码。这个'保持'使它比纯解释器慢(例如增加了开销和RAM使用导致交换和磁盘访问),但在重复执行一段代码时使其更快。对于代码,例如,它也可以比纯编译器更快。只重复调用一个函数,因为如果没有使用,它不会浪费时间编译程序的其余部分。

    最后,您可以在此矩形上找到其他位置,例如通过不永久保存已编译的代码,但再次从缓存中清除已编译的代码。这样你就可以这样在嵌入式系统上节省磁盘空间或RAM,代价是可能不得不第二次编译很少使用的代码。许多JIT编译器都这样做。

答案 1 :(得分:3)

现在许多执行环境都使用字节码(或类似的东西)作为代码的中间表示。因此,源代码首先编译成为一种中间语言,然后由虚拟机<解码(解码字节码指令集)或进一步编译进入机器代码,并由硬件执行。

很少有生产语言被解释为被预编译成某种中间形式。但是,很容易将这样的解释器概念化:只需考虑具有每种类型语言元素(if语句,for等)的子类的类层次结构,并且每个类具有{{1评估给定节点的方法。这通常也称为interpreter design pattern

作为示例,请考虑以下代码片段在假设的解释器中实现Evaluate语句(在C#中实现):

if

这是一个非常简单但功能齐全的解释器。

相关问题