关于JIT编译器和解释器的说明

我对JIT编译器和解释器有些怀疑。 从他们的定义开始:

(Interpreter)维基百科:

在计算机科学中,解释器是一种计算机程序,可直接执行(即执行)以编程或脚本语言编写的指令,而无需将其批量编译为机器语言。 解释器通常使用以下策略之一来执行程序:
1)解析源代码并直接执行其行为
2)将源代码翻译成一些有效的中间表示并立即执行此操作
3)明确执行由作为解释器系统一部分的编译器所做的存储的预编译代码[1]

(JIT COMPILER)维基百科:

在计算中,即时编译(JIT),也称为动态翻译,是在程序执行过程中 - 在运行时执行 - 而不是在执行之前编译完成的[1]。 大多数情况下,这包括翻译成机器码,然后直接执行,但也可以指向其他格式的翻译。

和从StackOverFlow:

即时编译是在执行之前将非本地代码(例如字节码)转换为本地代码。

我有4个问题:
1)总是说JIT =运行时,为什么解释器在运行时不工作? 在程序运行时,解释器是否在运行时翻译并执行每一行?
2)总是说JIT将非本地代码翻译为本机代码,那么又如何呢? 解释器是否将代码转换为本地代码? 如果我的过程没有转换为本机代码,我的过程如何执行一条指令? 所以解释器也需要将代码翻译成本地代码。
3)一个普通的解释器在需要执行时转换每一行,而使用一个JIT编译器时,每一行都在执行之前被翻译,所以当该行需要被执行时,它就变得可能了。 不是吗?
4)那么解释器和JIT编译器之间有什么不同?它们都在运行时执行程序,都从中间语言翻译为本地代码。


解释器不会将源代码翻译为本机机器码。 虽然您的计算机只能执行机器码,但它执行的机器码不一定是上级语言的翻译。 混乱? 我们来看一个简单的玩具例子...

考虑编程语言PrintForPony,它具有printsleep两个功能。 print函数接受一串字符作为其唯一参数并将其输出到stdout,而sleep将一个正整数作为其唯一参数,并将当前线程休眠一段时间。 PFP的伪BNF:

program        ::= statement_list
statement_list ::= statement | statement NEWLINE statement_list
statement      ::= print STRING | sleep POSITIVE_INTEGER

这是一个超级简单的Java实现,用于PFP的intepreter。 该程序将源文件作为唯一参数并对其进行解释:

import java.io.BufferedReader;
import java.io.FileReader;

public class PFPInterpreter {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(args[0]));
        String line = null;
        while ((line = br.readLine()) != null) {
            if (line.startsWith("print ")) {
                System.out.println(line.substring("print ".length()));
            } else if (line.startsWith("sleep ")) {
                Thread.sleep(Long.parseLong(line.substring("sleep ".length())));
            } else {
                throw new IllegalArgumentException("Unknown function: " + line);
            }
        }
    }
}

示例源文件:

print Hello, World!
sleep 1000
print Goodbye, World!

和样本输出:

$ java PFPInterpreter test.pfp 
Hello, World!
Goodbye, World!

PFP在任何时候都不会被翻译成本机机器码。 执行的本地机器代码是JVM,与此玩具语言无关。 我们也可以为PFP编写一个编译器,将代码翻译成可执行文件(我不打算这样做,因为这个答案已经太长了),但问题的关键是解释器不会编译为本地机器代码 - 它读取输入文件并根据内容执行某些操作。

回答问题:

1)解释器是运行你的代码的运行时。 我不确定你在哪里阅读过,解释器在运行时不工作,但我也不确定它应该是什么意思。

2)如上所示,否,解释器不会转换为本机机器码。 一个JIT编译器。 你的处理器只执行本地机器代码,但是本机代码可能是一个读取任意文件并根据内容执行某些操作的程序。 从这个意义上讲,解释器实际上只是一个典型的程序,它以文本文件的形式接受输入。

3)JIT编译相当复杂,我根本不是专家。 但是,对于Java的HotSpot,例如,在调用JIT编译器之前,代码块必须执行一定的次数(客户端为1500,服务器为IIRC为15,000)。 这可能是因为实际的编译不是免费的,编译后的本地机器代码很可能被缓存以供以后执行(这将解释许多执行的要求)。 这使得JIT编译是一次投资(时间和空间),在第一次执行时可能不会更快(可能甚至更慢),但后续执行将更快,因为不再需要编译,并且本机机器代码更高效。

4)见上文。

我希望这有助于!


1)总是说JIT =运行时,为什么解释器在运行时不工作? 在程序运行时,解释器是否在运行时翻译并执行每一行?

你是对的; 解释必然发生在运行时。

2)总是说JIT将非本地代码翻译为本机代码,那么又如何呢? 解释器是否将代码转换为本地代码? 如果我的过程没有转换为本机代码,我的过程如何执行一条指令? 所以解释器也需要将代码翻译成本地代码。

确实,所有的执行都是最终的本地代码。 解释器充满了实现非本地解释指令效果的功能。 这些功能都在本机代码中。

3)一个普通的解释器在需要执行时转换每一行,而使用一个JIT编译器时,每一行都在执行之前被翻译,所以当该行需要被执行时,它就变得可能了。 不是吗?

4)那么解释器和JIT编译器之间有什么不同?它们都在运行时执行程序,都从中间语言翻译为本地代码。

不同之处在于,JIT可以应用于比单个语句或指令更大的代码段 - JIT可以用于编译整个函数,类或甚至整个程序。

JIT编译的优点在于,为了将解释代码的一部分编译为本地代码的一次性成本交换,您可以节省解释的执行开销以及利用仅当您仅执行时无法执行的优化可以像解释器那样获得非本地代码的单指令视图。

这就是为什么JIT编译重复执行的代码部分是有意义的。 编译的成本只发生一次,而每次使用代码都会获得好处。


在这里,我将直接回答最后一个问题。

有时Java虚拟机被称为Java解释器; 然而,鉴于可以执行字节码的各种方式,该术语可能会产生误导。 虽然“Java解释器”是解释字节码的Java虚拟机的合理名称,但虚拟机还使用其他技术(例如实时编译)来执行字节码。 因此,尽管所有的Java解释器都是Java虚拟机,但并非所有的Java虚拟机都是Java解释器。

JIT指的是少数JVM实现中的执行引擎,速度更快,但需要更多内存,是一款即时编译器。 在这种方案中,方法的字节码在第一次被调用时被编译为本机机器码。 然后缓存该方法的本机机器码,以便在下次调用同一方法时重新使用它。

链接地址: http://www.djcxy.com/p/52561.html

上一篇: Clarifications on JIT Compiler and Interpreter

下一篇: compiler vs interpreter ( on basis of construction and design )