Fundamentals 22 min read

Understanding V8 Engine Memory Allocation and Garbage Collection

This article explains how the V8 JavaScript engine allocates memory, why garbage collection is necessary, describes the memory layout of new and old generations, reviews common GC algorithms such as reference counting, mark‑sweep, mark‑compact and incremental marking, and offers practical tips for writing high‑performance JavaScript code.

Xueersi Online School Tech Team
Xueersi Online School Tech Team
Xueersi Online School Tech Team
Understanding V8 Engine Memory Allocation and Garbage Collection

The article introduces the V8 engine, the dominant JavaScript execution engine used by Chrome and Node.js, highlighting its just‑in‑time compilation and sophisticated memory management that enable fast code execution.

It explains why automatic garbage collection (GC) is essential: unlike C/C++ where developers manually allocate and free memory, JavaScript relies on the engine to reclaim unreachable objects, preventing memory leaks and fragmentation.

V8's memory is limited (≈1.5 GB on 64‑bit, ≈800 MB on 32‑bit) and divided into two regions: the young generation (new space) and the old generation (old space). The young generation stores short‑lived objects, while the old generation holds long‑lived objects.

The article then details the most common GC algorithms used in V8:

Reference Counting : objects are freed when their reference count drops to zero; cannot collect cyclic references.

Mark‑Sweep : two phases (mark reachable objects, then sweep away the rest); may cause memory fragmentation.

Mark‑Compact : similar to mark‑sweep but compacts live objects to eliminate fragmentation.

Incremental Marking : splits the marking work into small slices to reduce pause times.

V8 applies these algorithms differently for the two generations. Young‑generation collection uses a copying algorithm (Scavenge) that swaps two semi‑spaces (From/To) and performs a quick mark‑compact. Old‑generation collection relies on mark‑sweep, mark‑compact, and incremental marking to handle larger, long‑lived objects.

Practical advice for writing high‑performance JavaScript is provided, including:

Avoid global variables (use var , let , or const properly).

Manually clear timers created with setTimeout or setInterval when they are no longer needed.

Be cautious with closures that capture variables, as they can keep objects alive unintentionally.

Remove DOM references after elements are detached to allow GC.

Use WeakMap and WeakSet for caches where keys should not prevent garbage collection.

Example of using WeakMap in Node.js to demonstrate weak references:

node --expose-gc // enable manual GC
global.gc();
let wm = new WeakMap();
let key = new Array(1000000);
wm.set(key, 1);
global.gc();
key = null; // drop strong reference
global.gc();

The example shows that even though the WeakMap still holds a reference to the array, the array is reclaimed because the reference is weak.

In summary, V8’s young‑generation GC uses the Scavenge copying algorithm with sub‑millisecond pauses, while the old generation employs incremental marking combined with mark‑sweep/mark‑compact to balance pause time and throughput. Write barriers are used to track reference changes efficiently. Understanding these mechanisms helps developers write memory‑friendly code and avoid common pitfalls that lead to leaks.

performancejavascriptMemory ManagementGarbage CollectionV8engine internals
Xueersi Online School Tech Team
Written by

Xueersi Online School Tech Team

The Xueersi Online School Tech Team, dedicated to innovating and promoting internet education technology.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.