Что такое Утечки Памяти?

Утечки памяти происходят когда приложения выделяют память но не освобождают её, вызывая рост потребления памяти до истощения системных ресурсов.

Частые Симптомы

  • Увеличение использования памяти со временем
  • Замедление приложения после длительного использования
  • Ошибки Out of Memory (OOM)
  • Паузы сборки мусора
  • Нестабильность системы

Утечки Памяти JavaScript

1. Отсоединенные DOM Узлы

// Утечка памяти - отсоединенные DOM узлы
let elements = [];

function createElements() {
    for (let i = 0; i < 1000; i++) {
        let div = document.createElement('div');
        elements.push(div);  // Сохранено но не присоединено
    }
}

// Исправлено
const container = document.getElementById('container');
for (let i = 0; i < 1000; i++) {
    container.appendChild(document.createElement('div'));
}
elements = [];  // Очистить ссылки

2. Event Listeners

// Утечка - listeners не удалены
function setupButton() {
    const button = document.getElementById('myButton');
    button.addEventListener('click', function heavyHandler() {
        const largeData = new Array(1000000).fill('data');
    });
}

// Исправлено - удалить listeners
function setupButtonFixed() {
    const button = document.getElementById('myButton');
    const handler = () => { /* ... */ };
    button.addEventListener('click', handler);
    return () => button.removeEventListener('click', handler);
}

Browser DevTools

Chrome DevTools

// 1. Сделать heap snapshot
// DevTools → Memory → Heap snapshot → Take snapshot

// 2. Сравнить snapshots
// Snapshot 1: Начальное состояние
// Выполнить действия
// Snapshot 2: После действий
// Сравнить для поиска удерживаемых объектов

Node.js Обнаружение Утечек

# Использовать clinic
npm install -g clinic
clinic doctor -- node app.js

# Генерировать нагрузку
ab -n 10000 -c 100 http://localhost:3000/

Автоматизированное Тестирование

// 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('Обнаружена утечка памяти!');
    }
    await browser.close();
}

Лучшие Практики

- [ ] Удалять event listeners при очистке
- [ ] Очищать все intervals/timeouts
- [ ] Использовать WeakMap для кэширования
- [ ] Очищать отсоединенные DOM узлы
- [ ] Реализовать лимиты размера кэшей

Заключение

Обнаружение утечек памяти критично для стабильности и производительности. Использование подходящих инструментов, реализация автоматизированных тестов и следование лучшим практикам предотвращает утечки до того как они затронут пользователей.