I have some doubts about a JIT Compiler and an Interpreter. Starting from their definitions:
(Interpreter) From Wikipedia:
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 COMPILER) From Wikipedia:
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.
and From StackOverFlow:
Just-in-time compilation is the conversion of non-native code, for example bytecode, into native code just before it is executed.
I have 4 questions:
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...
A JIT Compiler translates byte code into machine code and then execute the machine code. Interpreters read your high level language (interprets it) and execute what's asked by your program. Interpreters are normally not passing through byte-code and jit compilation.
The JIT compiler helps improve the performance of Java programs by compiling bytecodes into native machine code at run time. The JIT compiler is enabled by default. When a method has been compiled, the JVM calls the compiled code of that method directly instead of interpreting it.
Without JIT compiler, the JVM interpreter translates the byte-code line-by-line to make it appear as if a native application is being executed.
The JIT compiler aids in improving the performance of Java programs by compiling bytecode into native machine code at run time. The JIT compiler is enabled throughout, while it gets activated when a method is invoked. For a compiled method, the JVM directly calls the compiled code, instead of interpreting it.
An interpreter does not translate source code to native machine code. While your computer is only capable of executing machine code, the machine code that it executes does not necessarily have to be a translation of a higher-level language. Confusing? Let's look at a simple toy example...
Consider the programming language PrintForPony that has two functions, print
and sleep
. The print
function takes a string of characters as its only argument and prints it to stdout, while sleep
takes a positive integer as its only argument and puts the current thread to sleep for that amount of time. A pseudo-BNF for PFP:
program ::= statement_list
statement_list ::= statement | statement NEWLINE statement_list
statement ::= print STRING | sleep POSITIVE_INTEGER
Here's a super simple Java-implementation of an intepreter for PFP. The program takes a source file as its only argument and interprets it:
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);
}
}
}
}
A sample source file:
print Hello, World!
sleep 1000
print Goodbye, World!
And sample output:
$ java PFPInterpreter test.pfp
Hello, World!
Goodbye, World!
At no point in time is PFP translated into native machine code. The native machine code that is executed is the JVM, which has nothing to do with this toy language. We could also write a compiler for PFP that would translate the code into an executable file (I'm not going to, because this answer is already getting too long), but the point of the matter is that an interpreter does not compile to native machine code - it reads an input file and does something based on the contents.
To answer the questions:
1) An interpreter is the runtime that runs your code for you. I'm not sure exactly where you've read that interpreters don't work at runtime, but I'm also not sure what it's supposed to mean.
2) As demonstrated above, no, an interpreter does not translate to native machine code. A JIT-compiler does. Your processor only executes native machine code, but that native machine code could be a program that reads an arbitrary file and does something based on the contents. In that sense, an interpreter is really just a typical program that accepts input in the form of text files.
3) JIT-compilation is pretty complicated, and I am not an expert at all. However, with Java's HotSpot, for instance, code blocks must be executed a certain amount of times (1,500 for client, 15,000 for server, IIRC) before the JIT-compiler is invoked on them. This is likely because the actual compilation is not free, and it's very likely that the compiled native machine code is cached for later executions (which would explain the requirement of many executions). This makes JIT-compilation is an investment (in time and space) that may not be faster (perhaps even slower) on the first execution, but subsequent executions will be faster because compilation is no longer necessary, and the native machine code is more efficient.
4) See above.
I hope that helps!
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?
You are correct; interpretation necessarily occurs at run time.
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.
It's true that all execution is ultimately native code. The interpreter is filled with functions that implement the effects of non-native interpreted instructions. Those functions are in native code.
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...
The difference is that JIT can be applied to sections of code larger than just a single statement or instruction—JIT may be used to compile whole functions, classes, or even the entire program.
The advantage of JIT compilation is that, in exchange for the one-time cost of compiling a portion of the interpreted code into native code, you are saving the execution overhead of interpretation as well as exploiting optimizations that can't be performed when you only have a single-instruction-at-a-time view of the non-native code as an interpreter does.
This is why it makes sense to JIT compile portions of code that are executed repeatedly. The cost of compilation is incurred only once, while the benefits are reaped for each use of the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With