A Deep Dive Into V8 | AppSignal Blog (2024)

A majority of front-end developers deal with this buzzword all the time: V8. A big part of its popularity is due to the fact that it led JavaScript to a new level of performance.

Yes, V8 is very fast. But, how does it perform its magic and why is it so responsive?

The official docs state that “V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and Node.js, among others”.

In other words, V8 is a software developed in C++ that translates JavaScript into executable code i.e. machine code.

In this epiphanic moment, we start seeing things more clearly. Both Google Chrome and Node.js are just bridges to transport the JavaScript code to its final destination: machine code running in that specific machine.

Another important role in V8's performance play belongs to its generational and super accurate Garbage Collector. It was optimized to collect the objects that JavaScript no longer needs, using low memory.

Besides that, V8 counts on a set of other tools and features to improve some inherent JavaScript functionalities that historically, make the language slow (like its dynamic nature, for example).

In this article, we'll explore those tools (Ignition and TurboFan) and features in more detail. More than that, we'll cover the basics of V8's internal functioning, compilation and garbage collection processes, single-threaded nature, and more.

Let's go!

Now that you're diving into V8, you might be interested to dive into Application Monitoring for Node.js with AppSignal as well.

Starting With the Basics

How does machine code work? Machine code, in short, is a bunch of very low-level instructions that execute in specific parts of the machine’s memory.

The process of generating it, using C++ language as a reference, is similar to this:

A Deep Dive Into V8 | AppSignal Blog (1)

Before going any further, it’s important to point out that this is a compilation process, which is different from the JavaScript interpretation process. While the compiler, in fact, generates a whole program at the end of the process, the interpreter works as a program itself that does the job by reading the instructions (usually as scripts, like the JavaScript scripts) and translating them into executable commands.

The interpreting process can happen both on-the-fly (on which the interpreter parses and runs only the current command) or fully-parsed (that’s when the interpreter first translates the script entirely before proceeding with the respective machine instructions).

Back to the figure, the compilation process usually starts with the source code, as you know. You implement the code, save it and run. The running process, in turn, starts at the compiler. The compiler is a program, like any other, running on your machine. It then goes through all the code and generates object files. Those files are the machine code. They’re optimized code that runs in that specific machine, that’s why you’ll have to use a specific compiler when you move from one OS to another.

But you can’t execute separate object files, you need to combine them into a single file, the well-known .exe file (the executable file). That’s the linker’s job.

Finally, the loader is the agent responsible for transferring the code inside of that exe file to the virtual memory of your OS. It is basically a transporter. And here, you have your program finally up and running.

Sounds like a lengthy process, isn't it?

Most of the time (unless you’re a developer working with Assembly in a bank’s mainframe) you’ll spend your time programming in high-level languages: Java, C#, Ruby, JavaScript, etc.

The higher the language is, the slower it is. That’s why C and C++ are so much faster, they’re very close to the machine code language: the assembly language.

One of the main benefits of V8, apart from the performance, is the possibility of going beyond the ECMAScript standards and understand, for example, C++ as well:

A Deep Dive Into V8 | AppSignal Blog (2)

JavaScript is restricted to ECMAScript. And V8, in order to exist, must be compliant but not restricted to it.

Having the ability to incorporate C++ features into V8 is great. Since C++ has evolved to be very good at specificities of the OS — like file manipulation and memory/threads handling — having all this power in JavaScript's hands is very useful.

If you think about it, Node.js itself was born in a similar way. It followed a similar path to V8’s plus the server and networking capabilities.

Single-Threaded

If you’re a Node developer, you’ll be familiar with V8’s single-threaded nature. Each JavaScript execution context is directly proportional to one thread.

Of course, V8 manages the OS threading mechanism behind the scenes. It works with more than one thread because it’s a complex software and executes lots of stuff at the same time.

We have the main thread that executes the code, another one to compile the code (yes, we can’t stop the execution every time new code has to be compiled), some others to deal with garbage collection, and so on.

However, V8 creates an environment of a single thread for each of JavaScript’s execution context. The rest is kept under its control.

Imagine the stack of function calls your JavaScript code is supposed to make. JavaScript works by stacking one function on top of another, following the order by which each one was inserted/called. Before reaching each function’s content, we can’t know if it calls other functions. If and when that happens, then the called functions will be placed right after the caller in the stack.

When it comes to callbacks, for example, they are placed at the end of the pile.

The management of this stack organization and the memory the process will need is one of the main tasks of V8.

Ignition and TurboFan

Since version 5.9, released in May 2017, V8 comes with a new JavaScript execution pipeline that was built on top of Ignition, V8’s interpreter. It also includes a newer and better optimizing compiler ⁠— TurboFan.

These changes were totally focused on the overall performance and the difficulties Google developers were facing when adapting the engine to all the quick and considerable changes that the JavaScript universe brought up.

From the very beginning of the project, V8 maintainers were always worried about finding a good way to improve V8’s performance at the same pace JavaScript was evolving.

Now we can see huge improvements when running the new engine against the biggest benchmarks:

A Deep Dive Into V8 | AppSignal Blog (3)

Source: https://v8.dev/blog/launching-ignition-and-turbofan

You can read more about Ignition and TurboFan here and here.

This is another one of V8's magic tricks. JavaScript is a dynamic language. That means that new properties can be added, replaced and removed during execution time. This is not possible with languages like Java, for example, in which everything (classes, method, objects and variables) must be defined before program execution and can’t be dynamically changed after the app starts.

Because of its particular nature, the JavaScript interpreters usually perform a dictionary lookup based on a hash function to know exactly where this variable or that object is allocated in memory.

This costs a lot to the final process. In other languages, when objects are created, they receive an address (a pointer) as one of their implicit attributes. This way, we know exactly where they’re placed in memory and how much space to allocate.

With JavaScript, that’s impossible since we can’t map what doesn't exist yet. That’s where the hidden classes reign.

Hidden classes are almost the same as they are in Java: static and fixed classes with a unique address to locate them. However, rather than doing it before program execution, V8 will do it during runtime, every time we have a “dynamic change” in the object’s structure.

Let’s look at an example to clarify things. Consider the following code snippet:

javascript

function User(name, fone, address) { this.name = name; this.phone = phone; this.address = address;}

Within JavaScript’s prototype-based nature, every time we instantiate a new User object, let’s say:

javascript

var user = new User("John May", "+1 (555) 555-1234", "123 3rd Ave");

Then V8 creates a new hidden class. Let’s call it _User0.

A Deep Dive Into V8 | AppSignal Blog (4)

Each object has a reference to its class representation in memory. It’s the class pointer. At this point, since we just instantiated a new object, only a hidden class was created in memory. It is empty for now.

When you execute the first line of code in this function, a new hidden class is going to be created based on the previous one, this time _User1.

A Deep Dive Into V8 | AppSignal Blog (5)

It is basically the memory address of a User that has a name property. In our example, we’re not using users with just a name as an attribute, but every time you do it, this is the hidden class V8 will load as reference.

The name property is added to the offset 0 of your memory buffer, which means this will be considered our first attribute in the final order.

V8 will also add a transition value to the _User0 hidden class. This helps the interpreter to understand that every time a name property is added to a User object, the transition from _User0 to _User1 must be addressed.

When the second line in the function is called, the same process happens again and a new hidden class is created:

A Deep Dive Into V8 | AppSignal Blog (6)

You can see that the hidden classes keep track of the stack. One hidden class leads to another one in a chain maintained by the transition values.

The order in which the properties are added determines how many hidden classes V8 is going to create. If you change the order of the lines in the code snippet we’ve created, different hidden classes will be created as well. That’s why some developers try to maintain the order to reuse hidden classes and therefore, reduce the overhead.

Inline Caching

This is a term very common in the JIT (Just In Time) compilers world. And it connects directly with the concept of hidden classes.

Every time you call a function passing an object as a parameter, for example, V8 will take a look at this action and think: “Hmm, this object was successfully passed twice or more as a param to this function… why not store it in my cache for future calls rather than perform the whole time-consuming-hidden-class-validation process again?”

Let’s recap our last example:

javascript

function User(name, fone, address) { // Hidden class _User0 this.name = name; // Hidden class _User1 this.phone = phone; // Hidden class _User2 this.address = address; // Hidden class _User3}

After sending this User object twice instantiated with any values as a parameter to a function, V8 will jump the hidden class lookup and go directly to the offset’s properties. This is much faster.

However, remember that if you change the order of any attribute assignment in the function, it will result in different hidden classes, so V8 won’t be able to make use of the inline caching feature.

This is a great example to show that developers shouldn’t avoid getting to know the engine more intimately. On the contrary, having such knowledge will help your code perform better.

Garbage Collecting

Do you remember that we mentioned V8 collects memory garbage in a different thread? So, this helps a lot, since our program execution won’t get affected.

V8 uses the well-known strategy of “mark-and-sweep” to collect dead and old objects in memory. In this strategy, the phase where the GC scans memory objects to “mark” them for collection is a bit slow, because it pauses execution in order to achieve it.

However, V8 does it incrementally, i.e., for each GC stop, V8 tries to mark as many objects as possible. It makes everything faster because there’s no need to stop the entire execution until the collection finishes. In large applications, the performance improvement makes a lot of difference.

If you are monitoring your Node.js app with AppSignal, the Magic Dashboard for Garbage Collection stats for our Node.js integration can help you discover and fix this problem. No setting up is required, this dashboard will magically automatically appear among the rest of your dashboards.

A Continuous Ride

I hope you enjoyed this piece. The goal was to clarify a bit on V8's structural details, which are at many times misunderstood or ignored.

The whole thing is naturally complex. And it’s constantly evolving. But these are pretty much the core concepts.

At the time of writing this article, the GitHub repo counts 15.3k stars and 2.9k forks. You too can fork the open source code and change the V8 engine as you please. Add your own custom C++ instructions, change the way the hidden classes are dealt with, use your imagination.

But first, don’t forget to give a good read over the official docs. Good reading!

P.S. If you liked this post, subscribe to our new JavaScript Sorcery list for a monthly deep dive into more magical JavaScript tips and tricks.

P.P.S. If you are now interested to see how to monitor your Node.js app and zoom in on Garbage Collection, you might want to check out AppSignal applicaiton monitoring for Node.js.

A Deep Dive Into V8 | AppSignal Blog (2024)

FAQs

How is V8 so fast? ›

During execution V8 tracks how the program behaves, including tracking object shapes and types. Both the runtime execution metadata and bytecode are fed into the optimizing compiler to generate high-performance, often speculative, machine code that runs significantly faster than the interpreter can.

Why is js V8 fast? ›

The V8 engine gets its speed from the Just in Time (JIT) compilation of JS code to native machine code. The ignition interpreter, a key component of V8, compiles the JS code and generates non-optimized machine code.

Is the V8 engine written in C++? ›

V8 is Google's open source high-performance JavaScript and WebAssembly engine, written in C++. It is used in Chrome and in Node.js, among others. It implements ECMAScript and WebAssembly, and runs on Windows, macOS, and Linux systems that use x64, IA-32, or ARM processors.

What is Google Chrome's V8 engine? ›

Chrome V8 is a JavaScript engine, which means that it executes JavaScript code. Originally, JavaScript was written to be executed by web browsers. Chrome V8, or just V8, can execute JavaScript code either within or outside of a browser, which makes server-side scripting possible.

Is A V8 faster than a V16? ›

A V16 engine is pretty fast compared to other V engines. V16 engines have higher top speeds than V12, V10, V8, and V8. However, it is out of production so we will focus on the other four.

Is a V8 always faster than a V6? ›

Vehicles with a V8 tend to have more horsepower than vehicles with a V6, although this varies depending on the components of the engine. V8 engines generally have more torque although, the difference can be minimal in some models.

Is V8 faster than Python? ›

V8 is a world class compiler. Compared to ruby, Python, Erlang, php and that ilk it is lightning quick. (Pypy is a good match for it but it's not main street and you can't just use any module.) in terms of performance and popularity, v8/node stand pretty much alone as far as dynamic non-compiled environments.

Why do v8s sound so good? ›

Too low a frequency can be unpleasant, says Cerrato, adding this is a common problem with the “booming” noise of many four-cylinder engines. Because they have twice the cylinder count, a V8 engine's frequency is in a higher and generally more pleasing acoustic range.

Is V8 faster than SpiderMonkey? ›

V8 is the fastest, because it compiles all JS to machine code. SpiderMonkey (what FireFox uses) is fast too, but compiles to an intermediate byte-code, not machine code.

Who invented the V8 engine? ›

What we know is that in 1902, Leon Levavasseur took out a patent on the V8 engine. Initially, the V8 wasn't meant for cars, but for other types of motor vehicles. The first V8 engines were installed on boats and airplanes. These V8 engines were used to provide faster and better performing boats and airplanes.

Who manufactures V8 engines? ›

GM LS. Probably the most famous V8 in the world is the GM small block, specifically the LS family of engines that's been in everything from pick-up trucks to Corvettes and even boutique supercars, for the last 25 years.

What does V stand for in V8? ›

But, you may wonder what the 'V' means in V6 and V8. The 'V' represents the way cylinders are arranged in your engine. V-type engines have cylinders placed in a V-like shape, or to put it the other way, in two equal rows. This design is commonly used since it requires less space and can fit in most cars.

Which browser use V8? ›

Google created V8 for its Chrome browser, and both were first released in 2008. The lead developer of V8 was Lars Bak, and it was named for the powerful car engine. For several years, Chrome was faster than other browsers at executing JavaScript. The V8 assembler is based on the Strongtalk assembler.

What browsers use V8? ›

It is used in the Chrome web browser and other Chromium-based browsers, as well as in the Node. js runtime environment. The V8 engine is written in C++. It compiles JavaScript code to machine code before execution, which makes it very fast.

Does Safari use V8? ›

Safari has JavaScriptCore (also called Nitro) Edge was originally based on Chakra but has more recently been rebuilt using Chromium and the V8 engine.

Why are v8s so powerful? ›

The engine was designed and built by Edward R. Hewitt who emphasized the V8's superiority to the typical I4 and I6 and six-cylinder engines of the time because of its lower weight and easier to make crankshaft compared to the I6s of equal power as well as the V8 not taking much more space than a I4.

Why is a V8 more powerful? ›

As another answer has brought up, there is no inherent reason that a V8 makes more power but they are usually larger displacement and often by a factor of two to three. Assuming similar volumetric efficiency, the added displacement will generate more torque and assuming an ability to rev, more horsepower.

Is V8 really that good? ›

An occasional V8 is fine for most people, but you should still focus on having a variety of whole vegetables in your diet. A better bet would be to blend up some vegetables yourself at home. Or, even better, eat your vegetables and drink a glass of water instead.

Top Articles
Latest Posts
Article information

Author: Jeremiah Abshire

Last Updated:

Views: 5759

Rating: 4.3 / 5 (74 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Jeremiah Abshire

Birthday: 1993-09-14

Address: Apt. 425 92748 Jannie Centers, Port Nikitaville, VT 82110

Phone: +8096210939894

Job: Lead Healthcare Manager

Hobby: Watching movies, Watching movies, Knapping, LARPing, Coffee roasting, Lacemaking, Gaming

Introduction: My name is Jeremiah Abshire, I am a outstanding, kind, clever, hilarious, curious, hilarious, outstanding person who loves writing and wants to share my knowledge and understanding with you.