TGViewer
Настоящий JavaScript Настоящий JavaScript @true_js · 5.89K subscribers
Post #3575 363
Утечки памяти в production: как отлавливать то, что не видно в логах

Каждый раз, когда слышу "у нас утечка памяти", первая мысль - кто-то забыл удалить слушатель событий или не очистил setInterval. В production все сложнее: утечки копятся неделями, проявляются при определенной нагрузке, и локально их не воспроизвести.

Вот три рабочих инструмента.

Heap snapshots: как читать между строк

Снимаешь снапшот в Chrome DevTools (Memory -> Take heap snapshot). Сравниваешь два: до и после выполнения подозрительного сценария.

Ищешь объекты, которые:
- Не должны быть в памяти, но есть (старые DOM-ноды с замыканиями)
- Имеют неожиданно много экземпляров (10 000 объектов класса Widget)

Если видишь Closure с огромным retained size - это замыкание, которое держит ссылку на внешние данные. В production такая утечка часто возникает в SSR, когда обработчик запроса захватывает ссылку на глобальный кэш.

Memory tab: интерактивный детектив

Переходишь на вкладку Memory, выбираешь "Allocation instrumentation on timeline". Записываешь профиль при активной работе пользователя.

Красные пики в столбчатой диаграмме - места, где память выделяется, но не освобождается. Клик по пику покажет стек вызовов в момент аллокации.

Паттерн, который ловил так: React-компонент, при каждом ререндере создавал новый объект-конфигурацию и передавал в children - GC не успевал чистить, через час работы страница весила 200+ МБ.

Автоматизированные паттерны детекции

Ручной анализ хорошо, но в production нужно автоматическое обнаружение. Два подхода.

Performance Observer с проверкой usedJSHeapSize:

new PerformanceObserver((list) => {
const entries = list.getEntries();
if (performance.memory?.usedJSHeapSize > 200_000_000) {
console.warn('Memory warning', performance.memory);
}
}).observe({ type: 'resource', buffered: true });


Только в Chrome с флагом enable-experimental-web-platform-features. Типичная ошибка - использовать это без fallback в Safari или Firefox.

Кастомный мониторинг:

setInterval(() => {
const { usedJSHeapSize, totalJSHeapSize } = performance.memory;
const usagePercent = (usedJSHeapSize / totalJSHeapSize) * 100;
if (usagePercent > 80) {
sendMetric('memory_leak_risk', usedJSHeapSize);
}
}, 60000);


Не используй для продакшена бездумно - performance.memory есть не везде. Оборачивай в try/catch и делай fallback на navigator.userAgent.

Утечки в production - это не баги, а архитектурные проблемы. Если после каждого перехода по роуту память растет на 5-10% и не падает - ищи подписки в эффектах, которые не отписываются при размонтировании. Или глобальные кэши, которые никогда не чистятся.

Вывод: Надежная детекция утечек требует сочетания автоматических инструментов и ручного анализа heap snapshots, а не надежды на GC или банальные логи.
  • ❤ 1
More from @true_js
  1. Oct 3, 2026Post #3963
  2. Oct 2, 2026😅 Айтишник отправил в одну компанию три одинаковых резюме и только одно дошло до финала О…
  3. Oct 2, 2026Post #3961
  4. Oct 2, 2026🤣 Правильно расставленные приоритеты в моей жизни би лайк: 💥 xCode Journal
  5. Oct 1, 2026🤯 Люди взбунтовались против «пыточной для ИИ» На GitHub заметили открытый проект AI Tortu…
  6. Oct 1, 2026День в Заонежье начинается ещё в дороге. Мы встретим вас в аэропорту или на вокзале. Дальш…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →