Добавить в корзинуПозвонить
Найти в Дзене
Unity и геймдев | aks2dio

🧠 Утечки памяти 🧠

Ещё один полезный доклад с Unite 2025: How to find memory leaks with the Memory Profiler 📺 Не смотря на название, в докладе внимание уделено не только возможностям Memory Profiler. Есть информация и про типы памяти: Native, Managed, Graphics, Untracked. Есть про естественный рост потребления, про утечки памяти, про фрагментацию и её особенности с GC в Unity (т.е. про Boehm и CoreCLR). В некотором смысле, он хорошо дополняет доклад Understanding Unity memory 💬 ——————————— Ещё у меня есть короткие тематические нарезки из старых докладов:
Оглавление

Ещё один полезный доклад с Unite 2025: How to find memory leaks with the Memory Profiler 📺

Не смотря на название, в докладе внимание уделено не только возможностям Memory Profiler.

Есть информация и про типы памяти: Native, Managed, Graphics, Untracked.

Есть про естественный рост потребления, про утечки памяти, про фрагментацию и её особенности с GC в Unity (т.е. про Boehm и CoreCLR).

В некотором смысле, он хорошо дополняет доклад Understanding Unity memory 💬

Основные причины утечек

  • Частые аллокации.
  • Как следствие, фрагментация памяти.
  • Удержание ссылок на данные дольше, чем это необходимо, что мешает работе GC.
  • В частности, создание/загрузка ассетов без их последующего уничтожения.

Что к этому приводит

  • Отсутствие своевременной очистки статических ссылок на объекты и коллекции.
  • Отсутствие отписок для событий и делегатов.
  • Использование анонимных функций и лямбда-выражений для подписки: ими невозможно отписаться без костылей и пристроек. И они могут вызывать при этом замыкание (про замыкание 💬).
  • Отсутствие вызова Dispose у того, что это требует.
  • Неявное клонирование материалов: при обращении к .material может создаваться новый материал, который нужно уничтожать (нужно помнить про .sharedMaterial).
  • Злоупотребление асинхронными методами без CancellationToken или в Forget-режиме: могут работать неконтролируемо долго и удерживать ссылки на данные.

Как этого избежать

  • Сделал подписку — тут же задизайнил отписку. Сразу, не откладывая. Это и надёжнее (не забудешь), и получится архитектурно чище, т.к. придётся сразу продумать жизненный цикл реализуемой фичи.
  • Аналогично для Dispose.
  • Использовать симметрию: делать обратные действия в противоположных фазах. Это удобно дополняет прошлые пункты и упрощает контроль.
    Например, в OnEnable — подписались, в OnDisable — отписались. В Start — инициализировали, в OnDestroy — деинициализировали. И т.д.
  • Отказ от анонимных функций и лямбд для подписок: предпочитать методы.
  • Избегать хранения данных в статике. Только в случаях реальной необходимости или соответствия дизайну приложения.
  • Внимательно следить за статическими данными. И своевременно удалять оттуда неактуальные данные.
  • Выгружать загруженные или созданные ранее ассеты, при потере необходимости в них.
  • Использовать CancellationToken и/или принудительные таймауты для асинхронных методов.
  • Использовать пул объектов вместо частого создания и уничтожения одних и тех же объектов для снижения фрагментации.

———————————

Ещё у меня есть короткие тематические нарезки из старых докладов: