Clarifications on JIT Compiler and Interpreter
我对JIT编译器和解释器有些怀疑。
从他们的定义开始:
(口译员)来自维基百科:
In computer science, an interpreter is a computer program that directly executes, i.e. performs, instructions written in a programming or scripting language, without previously batch-compiling them into machine language. An interpreter generally uses one of the following strategies for program execution:
1) parse the source code and perform its behavior directly
2) translate source code into some efficient intermediate representation and immediately execute this
3) explicitly execute stored precompiled code[1] made by a compiler which is part of the interpreter system
(JIT编译器)来自维基百科:
In computing, just-in-time compilation (JIT), also known as dynamic translation, is compilation done during execution of a program – at run time – rather than prior to execution.[1] Most often this consists of translation to machine code, which is then executed directly, but can also refer to translation to another format.
从StackOverFlow:
Just-in-time compilation is the conversion of non-native code, for example bytecode, into native code just before it is executed.
我有4个问题:
1)总是说JIT =运行时,为什么解释器在运行时不工作?在程序运行时,解释器是否在运行时翻译并执行每一行?
2)总是说JIT将非本地代码转换为本机代码,那么呢?解释器不是将代码转换为本机代码吗?如果未将指令转换为本机代码,我的进程如何执行指令?因此,解释器也需要将代码转换为本机代码。
3)普通解释器在需要执行时转换每一行,而使用JIT编译器时,每一行都在执行之前进行转换,因此在需要执行该行的那一刻它是可用的。不是吗?
4)那么解释器和JIT编译器之间的真正区别是什么,它们都在运行时执行程序,从中间语言转换为本机代码......
解释器不会将源代码转换为本机机器代码。虽然您的计算机只能执行机器代码,但它执行的机器代码不一定必须是更高级语言的翻译。混乱?让我们来看一个简单的玩具示例......
考虑具有两个函数
1 2 3 | program ::= statement_list statement_list ::= statement | statement NEWLINE statement_list statement ::= print STRING | sleep POSITIVE_INTEGER |
这是PFP的解释器的超简单Java实现。该程序将源文件作为其唯一参数并解释它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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); } } } } |
示例源文件:
1 2 3 | print Hello, World! sleep 1000 print Goodbye, World! |
和样本输出:
1 2 3 | $ java PFPInterpreter test.pfp Hello, World! Goodbye, World! |
在任何时候,PFP都不会被翻译成本机代码。执行的本机机器代码是JVM,它与此玩具语言无关。我们还可以为PFP编写一个编译器,将代码转换为可执行文件(我不会,因为这个答案已经太长了),但问题的关键是解释器不能编译为本机机器代码 - 它读取输入文件并根据内容执行某些操作。
回答问题:
1)解释器是为您运行代码的运行时。我不确定你在哪里读到解释器在运行时不起作用,但我也不确定它应该是什么意思。
2)如上所示,不,解释器不会转换为本机机器代码。 JIT编译器可以。您的处理器只执行本机机器代码,但该本机机器代码可以是一个程序,它读取任意文件并根据内容执行某些操作。从这个意义上说,解释器实际上只是一个接受文本文件形式输入的典型程序。
3)JIT编译非常复杂,我根本不是专家。但是,使用Java的HotSpot,在调用JIT编译器之前,代码块必须执行一定次数(客户端为1,500,服务器为15,000,IIRC)。这很可能是因为实际的编译不是免费的,而且编译的本机机器代码很可能被缓存以供以后执行(这可以解释许多执行的要求)。这使得JIT编译是一种投资(在时间和空间上),在第一次执行时可能不会更快(甚至可能更慢),但随后的执行将更快,因为不再需要编译,并且本机机器代码更有效。
4)见上文。
我希望有所帮助!
1) It's always said JIT=runtime, why doesn't an Interpreter work at runtime? Doesn't an Interpreter translate and execute each line at runtime, while the program is running?
你是对的;解释必然发生在运行时。
2) It's always said JIT translates a non-native code to native-code, so what? Doesn't an interpreter convert a code to native code? How can my process execute an instruction if it is not translated to native code? So the interpreter needs to translate the code to native code too.
确实,所有执行都是最终的本机代码。解释器充满了实现非本机解释指令效果的函数。这些函数使用本机代码。
3) A normal interpreter translates each line when it needs to execute it, while using a JIT compiler each line is translated just before it is executed, so it is aviable in that moment when the line need to be executed. Isn't it?
4) So what are the real differene between an interpreter and a JIT compiler, both executes the program at runtime, both translate from an intermediate language to native code...
不同之处在于JIT可以应用于大于单个语句或指令的代码段 - mdash; JIT可用于编译整个函数,类甚至整个程序。
JIT编译的优点在于,作为将一部分解释代码编译为本机代码的一次性成本的交换,您节省了解释的执行开销以及利用仅在您执行时无法执行的优化像解释器一样,具有非本机代码的单指令视图。
这就是为什么JIT编译重复执行的代码部分是有意义的。编译的成本只发生一次,而每次使用代码都会带来好处。
在这里,我将直接回答最后一个问题。
有时Java虚拟机称为Java解释器; 但是,鉴于各种方式
哪个字节码可以执行,这个术语可能会产生误导。 虽然"Java解释器"是合理的
解释字节码的Java虚拟机的名称,虚拟机也使用其他技术
(例如即时编译)来执行字节码。 因此,尽管所有Java解释器都是Java虚拟机,但并非所有Java虚拟机都是Java解释器。
JIT指的是少数JVM实现中的执行引擎,一个更快但需要更多内存的实时引擎,是一个即时编译器。 在此方案中,方法的字节码在第一次调用方法时被编译为本机机器代码。 然后缓存该方法的本机机器代码,以便下次调用相同方法时可以重用它。