Уровень материала: 🐣 #junior
Ещё один полезный доклад с 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-режиме: могут работать неконтролируемо долго и удерживать ссылки на данные.(пример про AttachExternalCancellation 💬)
〰️〰️〰️〰️〰️〰️〰️
🍳 Как этого избежать 🗑️
🟣 Сделал подписку — тут же задизайнил отписку. Сразу, не откладывая. Это и надёжнее (не забудешь), и получится архитектурно чище, т.к. придётся сразу продумать жизненный цикл реализуемой фичи.
🟣 Аналогично для
Dispose.🟣 Использовать симметрию: делать обратные действия в противоположных фазах. Это удобно дополняет прошлые пункты и упрощает контроль.
Например, в OnEnable — подписались, в OnDisable — отписались. В Start — инициализировали, в OnDestroy — деинициализировали. И т.д.
🟣 Отказ от анонимных функций и лямбд для подписок: предпочитать методы.
🟣 Избегать хранения данных в статике. Только в случаях реальной необходимости или соответствия дизайну приложения.
🟣 Внимательно следить за статическими данными. И своевременно удалять оттуда неактуальные данные.
🟣 Выгружать загруженные или созданные ранее ассеты, при потере необходимости в них.
🟣 Использовать
CancellationToken и/или принудительные таймауты для асинхронных методов.🟣 Использовать пул объектов вместо частого создания и уничтожения одних и тех же объектов для снижения фрагментации.
〰️〰️〰️〰️〰️〰️〰️
Ещё у меня есть короткие тематические нарезки из старых докладов:
🟣 Про фрагментацию: YouTube 📺 | VK 🎥
🟣 Про пул объектов: YouTube 📺 | VK 🎥
