← Назад к вопросам

Как работает сборщик мусора?

1.0 Junior🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает сборщик мусора?

Сборщик мусора (Garbage Collector, GC) — это механизм в JavaScript для автоматического освобождения памяти, которая больше не используется программой. В отличие от C++ или Rust, где разработчик вручную управляет памятью, JavaScript делает это автоматически, но понимание того, как это работает, критично для оптимизации производительности.

Основной принцип: отслеживание ссылок

JavaScript отслеживает, какие объекты доступны из "корня" (root). Если объект недостижим, он считается "мусором" и может быть удален.

Типы сборки мусора

Mark-and-Sweep (самый распространённый алгоритм в V8):

  1. Mark фаза: начинаем с корневых объектов (глобальные переменные, локальные переменные) и рекурсивно помечаем все объекты, которые доступны
  2. Sweep фаза: удаляем все объекты, которые не были помечены

Как работает V8 (движок Chrome и Node.js)

V8 использует поколенческую сборку мусора (generational GC). Объекты делятся на две группы:

Young Generation (молодое поколение):

  • Только что созданные объекты
  • Небольшой размер (~32 MB)
  • Часто проверяется (более агрессивно)
  • Быстрая сборка

Old Generation (старое поколение):

  • Объекты, пережившие несколько GC циклов
  • Больший размер (~1 GB и более)
  • Реже проверяется
  • Медленнее, но нужна реже

Практический пример: создание и удаление объектов

function processData() {
  let largeObject = { data: new Array(1000000) }; // Создан объект
  
  // Используем объект
  console.log(largeObject.data.length);
  
  // Когда функция завершится, largeObject становится недостижимым
  // GC может удалить его
}

processData();
// largeObject удален (недостижим после окончания функции)

Проблема: утечки памяти

Утечка памяти происходит, когда объекты остаются достижимыми, хотя они больше не нужны:

// УТЕЧКА: объект в замыкании
let largeArray = null;

function createLeak() {
  largeArray = new Array(1000000); // Глобальная ссылка
  return function() {
    console.log(largeArray.length);
  };
}

const fn = createLeak();
// largeArray остаётся в памяти, даже если мы больше не используем fn

Типичные утечки памяти

1. Случайные глобальные переменные:

// БЕЗ использования 'let' или 'const'
function badFunction() {
  myVariable = new Array(1000000); // Создалась глобальная переменная!
}

// myVariable остаётся в памяти навсегда

2. Забытые обработчики событий:

const button = document.getElementById('btn');

button.addEventListener('click', function handler() {
  console.log('Clicked');
  // Если не удалить, обработчик остаётся навсегда
});

// ПОЗЖЕ:
button.removeEventListener('click', handler); // Нужно явно удалить

3. Интервалы и таймеры:

let id = setInterval(() => {
  console.log('Running'); // Продолжает работать, даже если не нужен
}, 1000);

// Должны очистить:
clearInterval(id);

4. DOM ссылки:

// Если удалили элемент из DOM, но сохранили ссылку
let element = document.getElementById('myDiv');
element.parentNode.removeChild(element);

// element всё ещё в памяти!
element = null; // Нужно явно обнулить

5. Замыкания с большими данными:

function createHandler() {
  const largeData = new Array(1000000); // Большой объект
  
  return function() {
    console.log('Handler called');
    // largeData доступна в замыкании
  };
}

const handler = createHandler();
// largeData остаётся в памяти, пока существует handler

Как проверить утечки памяти?

В Chrome DevTools:

  1. Открыть DevTools (F12)
  2. Перейти на вкладку "Memory"
  3. Нажать "Take heap snapshot"
  4. Выполнить операцию
  5. Нажать "Take heap snapshot" снова
  6. Сравнить - должны ли новые объекты остаться?

Best practices для предотвращения утечек

// ✅ ПРАВИЛЬНО: явная очистка

class EventManager {
  constructor() {
    this.listeners = [];
  }
  
  addEventListener(element, event, handler) {
    element.addEventListener(event, handler);
    this.listeners.push({ element, event, handler });
  }
  
  destroy() {
    // Очищаем все обработчики
    this.listeners.forEach(({ element, event, handler }) => {
      element.removeEventListener(event, handler);
    });
    this.listeners = [];
  }
}

// ✅ ПРАВИЛЬНО: использование WeakMap для кеша

const cache = new WeakMap();

function processData(object) {
  if (!cache.has(object)) {
    cache.set(object, expensiveComputation(object));
  }
  return cache.get(object);
}

// Когда object будет удален GC, он автоматически будет удален из WeakMap

Профилирование памяти в Node.js

// Проверить использование памяти
console.log(process.memoryUsage());
// Output: {
//   rss: 27.5 MB (resident set size - всё выделено ОС),
//   heapTotal: 10 MB (всего выделено для heap),
//   heapUsed: 5 MB (используется),
//   external: 0.3 MB,
//   arrayBuffers: 0.1 MB
// }

Влияние GC на производительность

// Во время GC приложение может "зависнуть"
// Major GC (старое поколение) может занять 100+ ms
// Major GC может стать узким местом для high-frequency приложений (трейдинг, игры)

// РЕШЕНИЕ: использовать Object Pools для переиспользования объектов

class Vector {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }
}

const vectorPool = [];

function getVector(x, y) {
  const vec = vectorPool.pop() || new Vector();
  vec.x = x;
  vec.y = y;
  return vec;
}

function returnVector(vec) {
  vectorPool.push(vec);
}

// Вместо создания новых объектов каждый раз, переиспользуем

GC в разных браузерах

  • V8 (Chrome, Node.js): поколенческая сборка, Scavenger и Mark-Compact
  • SpiderMonkey (Firefox): Zone-based GC
  • JavaScriptCore (Safari): Mark-and-Sweep с разными стратегиями
  • Chakra (старый Edge): различные оптимизации

Заключение

Сборщик мусора в JavaScript освобождает разработчиков от ручного управления памятью, но понимание его работы критично для написания эффективного кода. Утечки памяти часто возникают из-за забытых обработчиков событий, неочищенных таймеров и замыканий с большими данными. Использование DevTools для профилирования и Best practices для явной очистки ресурсов помогут избежать проблем с производительностью.

Как работает сборщик мусора? | PrepBro