¿Qué son las Fugas de Memoria?
Las fugas de memoria ocurren cuando las aplicaciones asignan memoria pero no la liberan, causando que el consumo crezca con el tiempo hasta agotar recursos del sistema.
Síntomas Comunes
- Uso memoria creciente en el tiempo
- Ralentización aplicación tras uso extendido
- Errores Out of Memory (OOM)
- Pausas garbage collection
- Inestabilidad sistema
Fugas de Memoria JavaScript
1. Nodos DOM Desvinculados
// Fuga memoria - nodos DOM desvinculados
let elements = [];
function createElements() {
for (let i = 0; i < 1000; i++) {
let div = document.createElement('div');
elements.push(div); // Almacenado pero nunca adjuntado
}
}
// Corregido
const container = document.getElementById('container');
for (let i = 0; i < 1000; i++) {
container.appendChild(document.createElement('div'));
}
elements = []; // Limpiar referencias
2. Event Listeners
// Fuga - listeners no removidos
function setupButton() {
const button = document.getElementById('myButton');
button.addEventListener('click', function heavyHandler() {
const largeData = new Array(1000000).fill('data');
});
}
// Corregido - remover listeners
function setupButtonFixed() {
const button = document.getElementById('myButton');
const handler = () => { /* ... */ };
button.addEventListener('click', handler);
return () => button.removeEventListener('click', handler);
}
DevTools Navegador
Chrome DevTools
// 1. Tomar heap snapshot
// DevTools → Memory → Heap snapshot → Take snapshot
// 2. Comparar snapshots
// Snapshot 1: Estado inicial
// Realizar acciones
// Snapshot 2: Después acciones
// Comparar para encontrar objetos retenidos
Node.js Detección Fugas
# Usar clinic
npm install -g clinic
clinic doctor -- node app.js
# Generar carga
ab -n 10000 -c 100 http://localhost:3000/
Testing Automatizado
// Puppeteer memory testing
const puppeteer = require('puppeteer');
async function testMemoryLeaks() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const measurements = [];
for (let i = 0; i < 50; i++) {
await page.click('#button');
const memory = await page.evaluate(() =>
performance.memory.usedJSHeapSize
);
measurements.push(memory);
}
const growth = measurements[49] - measurements[0];
if (growth > 50 * 1024 * 1024) {
console.error('Memory leak detected!');
}
await browser.close();
}
Mejores Prácticas
- [ ] Remover event listeners en cleanup
- [ ] Limpiar todos intervals/timeouts
- [ ] Usar WeakMap para caching
- [ ] Limpiar nodos DOM desvinculados
- [ ] Implementar límites tamaño caches
Conclusión
La detección de fugas de memoria es crítica para estabilidad y rendimiento. Usar herramientas apropiadas, implementar tests automatizados y seguir mejores prácticas previene fugas antes de impactar usuarios.