Understanding how V8 manages memory helps you write code that doesn't leak. Here's the deep internals.
V8 Memory Structure
V8 Heap
├── New Space (Young Generation) — ~1-8MB
│ ├── Semi-space A (From-space)
│ └── Semi-space B (To-space)
└── Old Space (Old Generation) — up to GBs
├── Old Pointer Space (objects with pointers)
├── Old Data Space (raw data, strings, numbers)
├── Large Object Space (objects > 256KB)
├── Code Space (compiled code)
└── Map Space (hidden classes)Scavenge (Minor GC)
Fast collection for the Young Generation. Uses Cheney's algorithm with two semi-spaces.
- New objects allocate in From-space
- When From-space is full, live objects are copied to To-space
- From-space and To-space swap roles
- Objects surviving two scavenges are promoted to Old Space
Scavenge is fast (1-2ms) because most objects die young (the generational hypothesis).
Mark-Sweep-Compact (Major GC)
For the Old Generation. Three phases:
- Mark: Starting from roots (global object, stack), traverse all reachable objects
- Sweep: Free memory of unmarked objects
- Compact: Move surviving objects to eliminate fragmentation
Common Memory Leaks
// 1. Forgotten event listeners
element.addEventListener("click", handler);
// element removed from DOM but handler still references it
// 2. Closures retaining large scopes
function process() {
const bigData = loadHugeDataset();
return function summary() {
return bigData.length; // bigData stays in memory!
};
}
// 3. Detached DOM trees
const elements = [];
function addElement() {
const div = document.createElement("div");
document.body.appendChild(div);
elements.push(div); // Array keeps reference even after DOM removal
}
// 4. Global variables
function leak() {
accidental = "I'm global!"; // Missing var/let/const
}Debugging Memory Issues
- Chrome DevTools Memory tab: Take heap snapshots, compare to find leaks
- Allocation Timeline: See where memory is allocated over time
- Performance Monitor: Watch JS heap size in real-time
- --max-old-space-size: Increase Node.js heap limit for large datasets