What is V8?
V8 is Googleβs open-source, high-performance JavaScript engine, written in C++. Itβs the engine that powers:
- Google Chrome (since 2008)
- Node.js (since 2009)
- Deno
- Electron (VS Code, Slack, Discord)
- Edge (Chromium-based)
JavaScript Source Code
β
βΌ
ββββββββββββ
β Parser β
ββββββ¬ββββββ
β
βΌ
ββββββββββββ
β Interpreter β βββ Ignition (fast startup)
ββββββ¬ββββββ
β
βΌ
ββββββββββββββββ
β Compiler β βββ TurboFan (optimised code)
β (TurboFan) β
ββββββββββββββββ
β
βΌ
Machine Code
How V8 Works: JIT Compilation
Unlike traditional interpreted languages (Python, Ruby), V8 compiles JavaScript to machine code at runtime. This is called Just-In-Time (JIT) compilation.
| Step | Phase | What Happens |
|---|---|---|
| 1 | Parsing | Source code β Abstract Syntax Tree (AST) |
| 2 | Ignition | AST β Bytecode (interpreter) |
| 3 | Profiling | Hot code paths are identified |
| 4 | TurboFan | Hot bytecode β Optimised machine code |
| 5 | Deoptimisation | If assumptions fail, fall back to bytecode |
Hidden Classes & Inline Caching
V8 optimises property access using hidden classes (maps) and inline caching (IC).
// V8 creates a hidden class for this shape
function Point(x, y) {
this.x = x; // Hidden class created here
this.y = y; // Transition to new class
}
const p1 = new Point(1, 2);
const p2 = new Point(3, 4); // Reuses the same hidden classes
Performance tip: Always initialise object properties in the same order. V8 reuses hidden classes when object shapes are identical.
Bad vs Good
// β Bad β different property order every time
function createUser(role) {
const user = {};
if (role === 'admin') {
user.role = 'admin';
user.permissions = ['all'];
} else {
user.permissions = ['read'];
user.role = 'user';
}
return user;
}
// β
Good β consistent property order
function createUser(role) {
const user = { role: 'user', permissions: [] };
if (role === 'admin') {
user.role = 'admin';
user.permissions = ['all'];
}
return user;
}
Garbage Collection
V8 uses a generational garbage collector:
New Space (Young Gen) Old Space (Old Gen)
ββββββββββββββββββββ ββββββββββββββββββββ
β New objects ββββΊβββββββ Surviving objectsβ
β Small, short-livedβ GC β Long-lived β
β Collected often β β Collected rarely β
ββββββββββββββββββββ ββββββββββββββββββββ
- Scavenge β fast collection on young generation
- Mark-Sweep-Compact β slower full collection on old generation
Measuring Performance in Node.js
1. Built-in performance API
const { performance, PerformanceObserver } = require('perf_hooks');
performance.mark('start');
// ... your code ...
performance.mark('end');
performance.measure('My Task', 'start', 'end');
const obs = new PerformanceObserver((items) => {
console.log(items.getEntries()[0].duration, 'ms');
});
obs.observe({ entryTypes: ['measure'] });
2. Timing with console.time
console.time('array-loop');
const arr = new Array(1000000);
for (let i = 0; i < arr.length; i++) {
arr[i] = i * 2;
}
console.timeEnd('array-loop');
// array-loop: 12.345ms
3. V8 Flags
# See all V8 options
node --v8-options
# Trace optimisations
node --trace-opt my-script.js
# Trace deoptimisations
node --trace-deopt my-script.js
Node.js Performance Best Practices
// β
Do: Cache property lookups
const len = arr.length;
for (let i = 0; i < len; i++) { /* ... */ }
// β Don't: Delete properties (breaks hidden classes)
const obj = { a: 1, b: 2 };
delete obj.a; // Forces class transition
// β
Do: Use monomorphic functions
function add(a, b) { return a + b; } // Always called with numbers
// β Don't: Polymorphic calls
function add(a, b) { return a + b; }
add(1, 2); // number + number
add('a', 'b'); // string + string β triggers deopt
// β
Do: Use typed arrays for numeric data
const buffer = new Float64Array(1000000);
Key Takeaways
- V8 is the JavaScript engine behind Node.js β written in C++, JIT-compiles JS to machine code
- Uses Ignition (interpreter) + TurboFan (optimising compiler)
- Hidden classes and inline caching make property access fast
- Generational GC keeps memory pressure low
- Consistent object shapes, monomorphic functions, and avoiding
deletekeep V8 happy - Use
console.timeandperf_hooksto measure real-world performance