我刚与一位同事进行了对话,并谈论了V8 JavaScript引擎。根据维基百科,
V8在执行之前将JavaScript编译为本机机器代码,而不是更传统的技术,例如解释字节码或将整个程序编译为机器代码并从文件系统执行它。
其中(如果我错了,请纠正我)" 解释字节码"是Java的工作方式," 编译整个程序"适用于C或C ++等语言。现在我们想知道,辩论并提出关于差异,相似性的错误断言和推定。为了结束这一点,我建议问问专家。
那么,谁能够
答案 0 :(得分:13)
由于一个简单的原因,几乎不可能回答你的问题:没有一些方法,它们是一个连续统一体。这个连续体中涉及的实际代码也是完全相同的,唯一的区别在于事情发生时,以及中间步骤是否以某种方式保存。这个连续体中的各个点(不是一条线,一条渐进线,而是一条可以靠近的不同角落的矩形):
例如,纯粹的解释编程语言几乎没有做#4和#2有点隐含地发生在1到3之间,所以你几乎没有注意到它。它只是读取代码的各个部分,并立即对它们做出反应。这意味着实际开始执行的开销很低,但是在一个循环中,相同的文本行被读取并重新读取。
在矩形的另一个角落,传统上有编译的语言,通常,第4项包含将实际机器代码永久保存到文件中,然后可以在以后运行。这意味着你在开始时等待相当长的时间直到整个程序被翻译(即使你只是在其中调用单个函数),但OTOH循环更快,因为源不需要是再读一遍。
然后介于两者之间,例如: 虚拟机:为了便于携带,许多编程语言不能编译为实际的机器代码,而是编译为字节代码。然后有一个编译器生成字节代码,以及一个解释器,它接受这个字节码并实际运行它(有效地#34;将其转换为机器代码")。虽然这通常比编译并直接转到机器代码要慢,但是将这种语言移植到另一个平台更容易,因为您只需要移植字节码解释器,这通常是用高级语言编写的,这意味着你可以使用现有的编译器执行此操作"有效转换为机器代码",并且不必为要运行的每个平台制作和维护后端。此外,如果您可以执行一次编译到字节码,然后只分发编译的字节码,这样可以更快,这样其他人就不必花费CPU周期。在代码上运行优化器,只需支付字节码到本机的翻译费用,这在您的使用案例中可以忽略不计。此外,您还没有分发您的源代码。
介于两者之间的另一件事是即时编译器(JIT),它实际上是一个解释器,它以编译的形式保存它运行过一次的代码。这个'保持'使它比纯解释器慢(例如增加了开销和RAM使用导致交换和磁盘访问),但在重复执行一段代码时使其更快。对于代码,例如,它也可以比纯编译器更快。只重复调用一个函数,因为如果没有使用,它不会浪费时间编译程序的其余部分。
最后,您可以在此矩形上找到其他位置,例如通过不永久保存已编译的代码,但再次从缓存中清除已编译的代码。这样你就可以这样在嵌入式系统上节省磁盘空间或RAM,代价是可能不得不第二次编译很少使用的代码。许多JIT编译器都这样做。
答案 1 :(得分:3)
现在许多执行环境都使用字节码(或类似的东西)作为代码的中间表示。因此,源代码首先编译成为一种中间语言,然后由虚拟机<解码(解码字节码指令集)或进一步编译进入机器代码,并由硬件执行。
很少有生产语言被解释为而被预编译成某种中间形式。但是,很容易将这样的解释器概念化:只需考虑具有每种类型语言元素(if
语句,for
等)的子类的类层次结构,并且每个类具有{{1评估给定节点的方法。这通常也称为interpreter design pattern。
作为示例,请考虑以下代码片段在假设的解释器中实现Evaluate
语句(在C#中实现):
if
这是一个非常简单但功能齐全的解释器。