编译和解释之间有什么区别? [英] What is the difference between compilation and interpretation?

查看:138
本文介绍了编译和解释之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚与一位同事交谈,并且在哪里谈论V8 JavaScript引擎。根据Wikipedia的说法,


V8在执行之前将JavaScript编译为本地机器代码,而不是像解释这样的传统技术。字节码或将整个程序编译为机器代码,然后从文件系统执行。


其中(如果我输入错了,请纠正我) 解释字节码是Java的工作方式, 编译整个程序将适用于C或C ++之类的语言。现在我们想知道,辩论并提出关于差异,相似性的错误主张和假设。为此,我建议向SO专家咨询。



因此,谁能够


  1. 命名,解释和/或引用所有主要方法(例如,预编译与运行时解释)

  2. 以可视化方式或提供有关源,编译和解释之间关系的方案

  3. 给出了#1主要方法的示例(名称编程语言)。






注意:




  • 我不是在寻找关于不同范式的漫长而平淡的论文,而是视觉上支持的快速概述。

  • 我知道Stackoverflow并非旨在成为程序员的百科全书(而是一个针对特定问题的问答平台)。但是,由于我可以找到很多受欢迎的问题,因此可以为某些主题提供百科全书式的视图(例如 [1] [2] [3] [4] [5] ),我开始了这个问题。

  • 如果该问题会宁可适合其他StackExchange网站(例如 cstheory ),请让我知道或将此问题标记为审核对象。


解决方案

出于一个简单的原因,几乎不可能回答您的问题:在一些方法中,它们是连续的。这个连续体涉及的实际代码也完全相同,唯一的区别是发生的时间以及是否以某种方式保存了中间步骤。此连续体上的各个点(不是单条线,不是一个曲线,而是更多的是可以接近的具有不同角的矩形):


  1. 阅读代码

  2. 了解代码

  3. 执行您了解的内容

  4. 沿道路缓存各种中间数据,甚至将其持久保存到磁盘。

例如,一个纯粹的解释编程语言几乎没有做#4和#2有点隐式地发生在1和3之间,因此您几乎不会注意到它。它只是读取代码部分,并立即对其做出反应。这意味着实际开始执行的开销很小,但是例如循环读取相同的文本行,然后再次重新读取。





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



然后中间有一些东西,例如虚拟机:出于可移植性,许多编程语言都不会编译为实际的机器代码,而是编译为字节代码。然后有一个生成字节码的编译器,以及一个使用该字节码并实际运行它的解释器(有效地将其转换为机器代码)。尽管这通常比编译直接进入机器代码要慢,但是将这种语言移植到另一个平台要容易得多,因为您只需要移植通常用高级语言编写的字节码解释器,这意味着您可以使用现有的编译器来执行对机器代码的有效转换,而不必为要在其上运行的每个平台制作和维护后端。另外,如果您一次可以对字节码进行编译,然后仅分发已编译的字节码,则此可以更快,这样其他人就不必花费CPU周期。在代码上运行优化器,仅支付字节码到本机的转换,这在您的用例中可以忽略不计。另外,您不会分发源代码。



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



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


I just had a conversation with a colleague and where were talking about the V8 JavaScript engine. According to Wikipedia,

V8 compiles JavaScript to native machine code [...] before executing it, instead of more traditional techniques such as interpreting bytecode or compiling the whole program to machine code and executing it from a filesystem.

where (correct me if I'm wrong) "interpreting bytecode" is the way Java works, and "compiling the whole program" would apply for languages like C or C++. Now we were wondering, debating and posing false assertions and presumptions about differences, similarities. To end this, I recommended asking the experts on SO.

So, who is able to

  1. name, explain and/or reference all major methods (e.g. precompiling vs. runtime interpretation)
  2. to visualize or to provide a scheme about the relations between source, compilation and interpretation
  3. give examples (name programming languages) for the major methods of #1.


Notes:

  • I am not looking for a long prosaic essay about the different paradigms, but an visually supported, quick overview.
  • I know that Stackoverflow is not intended to be a encyclopedia for programmers (but rather a Q&A platform for more specific questions). But since I can find a lot of popular questions, that kind of provide an encyclopedic view to certain topics (e.g. [1], [2], [3], [4], [5]), I started this question.
  • If this question would rather fit into any other StackExchange site (e.g. cstheory), please let me know or flag this question for moderation.

解决方案

It's near-impossible to answer your question for one simple reason: There aren't a few approaches, they are rather a continuum. The actual code involved across this continuum is also fairly identical, the only difference being when things happen, and whether intermediate steps are saved in some way or not. Various points across this continuum (which is not a single line, a progression, but rather more of a rectangle with different corners to which you can be close) are:

  1. Reading source code
  2. Understanding the code
  3. Executing what you understood
  4. Caching various intermediate data along the road, or even persistently saving them to disk.

For example, a purely interpreted programming language Pretty much doesn't do #4 and #2 kinda happens implicitly between 1 and 3 so you'd barely notice it. It just reads sections of the code, and immediately reacts to them. This means there is low overhead to actually starting execution, but e.g. in a loop the same lines of text get read and re-read again.

In another corner of the rectangle, there are traditionally compiled languages, where usually, item #4 consists of permanently saving actual machine code to a file, which can then be run at a later time. This means you wait a comparatively long while at the beginning until the entire program is translated (even if you're only calling a single function in it), but OTOH loops are faster because the source doesn't need to be read again.

And then there are things in between, e.g. a virtual machine: For portability, many programming languages don't compile to actual machine code, but to a byte code. There is then a compiler that generates the byte code, and an interpreter that takes this bytecode and actually runs it (effectively "turning it into machine code"). While this is generally slower than compiling and going directly to machine code, it is easier to port such a language to another platform, as you only have to port the bytecode interpreter, which is often written in a high-level language, meaning you can use an existing compiler to do this "effective translation to machine code", and don't have to make and maintain a backend for each platform you want to run on. Also, this can be faster if you can perform the compilation to bytecode once, and then only distribute the compiled bytecode, so that other people do not have to spend CPU cycles on e.g. running the optimizer over your code, and only pay for the bytecode-to-native translation, which may be negligible in your use case. Also, you're not handing out your source code.

Another thing in between would be a Just-in-Time compiler (JIT), which is effectively a interpreter that keeps around code it has run once, in compiled form. This 'keeping around' makes it slower than a pure interpreter (e.g. added overhead and RAM use leading to swapping and disk access), but makes it faster when repeatedly executing a stretch of code. It can also be faster than a pure compiler for code where e.g. only a single function is repeatedly called, because it doesn't waste time compiling the rest of the program if it isn't used.

And finally, you can find other spots on this rectangle e.g. by not saving compiled code permanently, but purging compiled code from the cache again. This way you can e.g. save disk space or RAM on embedded systems, at the cost of maybe having to compile a seldom-used piece of code a second time. Many JIT compilers do this.

这篇关于编译和解释之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆