debugjavascriptnodejsMajorpending
Debug: Node.js application memory leak detection
Viewed 0 times
memory leakheap snapshotevent listener leakclosure leaklru cache
Error Messages
Problem
Node.js application memory usage grows continuously over time, eventually crashing with heap out of memory.
Solution
Detect and fix Node.js memory leaks:
Common leak sources:
// 1. Monitor memory usage over time
setInterval(() => {
const used = process.memoryUsage();
console.log(JSON.stringify({
rss: Math.round(used.rss / 1024 / 1024) + 'MB',
heapUsed: Math.round(used.heapUsed / 1024 / 1024) + 'MB',
heapTotal: Math.round(used.heapTotal / 1024 / 1024) + 'MB',
external: Math.round(used.external / 1024 / 1024) + 'MB',
}));
}, 30000); // Every 30s
// 2. Take heap snapshots for comparison
// Start with: node --inspect app.js
// Chrome DevTools -> Memory -> Take heap snapshot
// Take snapshot at start, then after a few minutes
// Compare: look for objects that grow in count
// 3. Programmatic heap snapshot
const v8 = require('v8');
const fs = require('fs');
function writeHeapSnapshot() {
const filename = v8.writeHeapSnapshot();
console.log(`Heap snapshot: ${filename}`);
}
// Trigger with: kill -USR2 <pid>
process.on('SIGUSR2', writeHeapSnapshot);Common leak sources:
// LEAK 1: Event listeners not removed
class Processor {
start(emitter) {
// BAD: adds new listener on every call!
emitter.on('data', this.handleData.bind(this));
}
// FIX: Store reference and remove
start(emitter) {
this._handler = this.handleData.bind(this);
emitter.on('data', this._handler);
}
stop(emitter) {
emitter.removeListener('data', this._handler);
}
}
// LEAK 2: Closures holding large references
function processLargeData(hugeArray) {
return function getLength() {
return hugeArray.length; // hugeArray stays in memory!
};
}
// FIX: Copy only what you need
function processLargeData(hugeArray) {
const len = hugeArray.length;
return function getLength() {
return len;
};
}
// LEAK 3: Global caches without size limits
const cache = {}; // Grows forever!
// FIX: Use LRU cache with max size
const LRU = require('lru-cache');
const cache = new LRU({ max: 500 });
// LEAK 4: Uncleared timers/intervals
const interval = setInterval(work, 1000);
// FIX: Clear when done
clearInterval(interval);Why
Memory leaks in Node.js usually come from retained references: event listeners, closures, caches, or timers. The heap snapshot comparison technique pinpoints exactly what's growing.
Context
Long-running Node.js applications
Revisions (0)
No revisions yet.