JS Works - Draft
JS Works - Draft
engine
The first post of the series focused on providing an overview of
the engine, the runtime and the call stack. This second post will
be diving into the internal parts of Google’s V8 JavaScript
engine.
Overview
Before diving into JS engine, lets discuss basic working of any
programming language. The computer is made of
microprocessors and we write code to instruct them. But main
question is how we make microprocessors understand the code
that we are writing? They don’t understand high level languages
like Java, C#, Python etc., but only understand machine code.
The main thread does what you would expect: fetch your
code, compile it and then execute it.
There’s also a separate thread for compiling, so that the main
thread can keep executing while the former is optimizing the
code.
A Profiler thread that will tell the runtime on which methods
we spend a lot of time so that Crankshaft can optimize them.
A few threads to handle Garbage Collector sweeps.
Hidden class
JavaScript is a dynamic programming language which means that properties can
easily be added or removed from an object after its instantiation. For example, in the
code snippet below an object is instantiated with the properties “make” and “model”;
however, after the object has already been created, the “year” property is
dynamically added.
this.make = make;
this.model = model;
myCar.year = 2013;
Inline caching
V8 takes advantage of another technique for optimizing
dynamically typed languages. It is called inline caching. It relies
on the observation that repeated calls to the same method tend
to occur on the same type of object.
The two objects are basically the same but the “a” and “b” properties were created in different
order.
Garbage collection
For garbage collection, V8 uses a traditional generational
approach of mark-and-sweep to clean the old generation. The
marking phase is supposed to stop the JavaScript execution. In
order to control GC costs and make the execution more stable,
V8 uses incremental marking: instead of walking the whole
heap, trying to mark every possible object, it only walks part of
the heap, then resumes normal execution. The next GC stop will
continue from where the previous heap walk has stopped. This
allows for very short pauses during the normal execution. As
mentioned before, the sweep phase is handled by separate
threads.
Ignition and TurboFan
With the release of V8 5.9 in 2017, a new execution pipeline was
introduced. This new pipeline achieves even bigger performance
improvements and significant memory savings in real-
world JavaScript applications.
You can check out the blog post from the V8 team about the
topic here.
This means that overall V8 will have much simpler and more
maintainable architecture going forward.
Improvements on Web and Node.js benchmarks
These improvements are just the start. The new Ignition and
TurboFan pipeline pave the way for further optimizations that
will boost JavaScript performance and shrink V8’s footprint in
both Chrome and Node.js in the coming years.