DEV Community

Alireza Ebrahimkhani
Alireza Ebrahimkhani

Posted on • Edited on

What JIT really is ? (Part 2)

In the previous part, I talked about what compilers and interpreters are, and in this part, I want to continue the content. If you have not read the previous part, you can read it from this link.

Let's have a look at the pros and cons of each. First of all, interpreters are quick to get up and running, right? Because if we go to our example with an interpreter, we don't have to convert into another language.There's no compilation step before you can start running your code, you just give this to an interpreter and the interpreter starts translating their first line and just runs the code for us because of this, an interpreter is a natural fit for something like JavaScript, right, a JavaScript file gets sent from the server to the browser to the client on the front end and we want that JavaScript to execute right away because our users are going to be waiting on the Web page trying to interact with our application. And JavaScript originally was created for the browser, so being able to interpret JavaScript and run it as fast as possible.

Well, that was ideal and this is exactly why it JavaScript used interpreters at the beginning but there's a con with using an interpreter and this is the same problem that Google had back in the day when they had Google Maps running a lot of JavaScript, but it will get slower and slower and slower because the problem with interpreters is that when you're running the same code more than once, for example, if you're in a loop like this one over here where we're running this piece of code over and over and over, even though it gives us the same result.

Calculation code

It can get really, really slow. The compiler actually helps us here.It takes a little bit more time to start up because it has to go through that compilation step at the beginning, go through our code, understand it and spit it out into a another language.But the compiler will be smart enough and if it sees code like that we just loop over and it has the same inputs returning the same outputs it can actually just simplify this code and instead of calling function multiple times, it can just replace this function with something like nine because a compiler doesn't need to repeat the translation for each pass through in that loop, the code generated from it is actually faster and these sort of edits that compilers do are called optimization.

So let's go back to that question, interpreter or a compiler?
Which one is better?

They both have their pros and cons compiler obviously takes a little bit longer to get up and running,but the code is going to eventually run faster or interpreter that is really fast to get up and running but unfortunately doesn't do any optimizations.

Is there a way that we can get the best of both worlds and this is what some engineers came up with in late 2000, and if we use Google as our example with the V8 engine, what if we combine the best of both worlds? What if instead of using the compiler and interpreter, we combine these two and create something called a JIT compiler or just in time compiler ?

This is exactly what Browsers started doing, Browsers started mixing compilers, specifically these JIT compilers for Just in Time compilation to make the engines faster.

So let's see how V8 engine does this underneath the hood in order to use the best of both worlds remember, we passed the code, we turn it into an abstract syntax tree (AST), and then this code initially goes to an interpreter. Initially, the code gets sent to the interpreter and in the V8 engine, this is called ignition.I know they have a really cool sounding names to make them sound like they do things fast but this interpreter and the V8 engine is called ignition and it takes AST and it spits out bytecode and remember, bytecode is code that's not as low level as machine code, but it's code that is able to be interpreted by the JavaScript engine in order to run our programs.

So that's the first step, but there's something called a profiler that's checking out our code. This profiler also called a monitor, monitors and watches our code as it runs.
It makes notes on how we can optimize this code, such as how many times it is being run, what types are used and how we can possibly optimize code and using this profiler as the code is running through our interpreter, which tells our browser what to do.

If the same lines of code are run a few times we actually pass off some of this code to the compiler or a JIT compiler, because as the code is running the interpreter is going to say, hey, here's some code for you to optimize, passes it off to the compiler and the compiler as the application is running, takes a code and compiles it or modifies it.
So it does what you ask it to, but trying to make optimizations so it runs faster and it then replaces the sections where it could be improved of the bytecode with optimized machine code.

So that code, that optimized code is used from that point on instead of the slower bytecode, so it mixes and matches things and it constantly runs through this loop and this means that the execution speed of JavaScript code will be improving.

This means that the execution speed of the JavaScript code that we entered into the engine is going to gradually improve because the profiler and the compiler are constantly making updates and changes to our bytecode in order to be as efficient as possible so interpreter allows us to run the code right away and the compiler and profiler allows us to optimize this code as we're running.

That's where the name comes from JIT compiler and this compiler for V8 is called Turbo Fan again, a cool sounding name to make it sound like things are going fast and by the way, just a bit of a fun fact, previous versions of V8 Engine actually used JIT compilers with really cool sounding names, but they changed it to this method because there are some faster optimizations that they could do.

So why do we just learn all of this, you can write JavaScript without knowing any of this stuff and you'll be fine. Now that we know how the engine works underneath the hood, we can write more optimized code that the compiler can take and run faster than our regular JavaScript and we also can use this knowledge to make sure that we don't confuse the compiler because the compiler is imperfect, it can make mistakes and it can try to optimize code that actually does the opposite and if it makes a mistake and it does something unexpected, it does which takes even longer time to reverted back to the interpreter.

I hope this paper is useful for you and helps you better understand the JIT compiler.

Top comments (1)

Collapse
 
moghimi profile image
Mohammad

perfect !