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

Как находишь утечки памяти?

2.7 Senior🔥 141 комментариев
#Управление памятью

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Методы поиска и устранения утечек памяти в Unity

Поиск утечек памяти — критическая часть разработки на Unity, особенно для мобильных платформ и длительных игровых сессий. Я использую многоуровневый подход, сочетающий инструменты Unity, ручной анализ и профилактические меры.

Основные инструменты анализа

Unity Profiler — основной инструмент для первичной диагностики:

  • Отслеживаю Managed Memory (C# объекты) и Native Memory (нативные ресурсы Unity)
  • Использую Deep Profile для точного определения методов-виновников
  • Анализирую графики памяти на предмет стабильного роста
// Пример проблемного кода с утечкой через захват контекста
void Update() {
    // Проблема: лямбда захватывает контекст, создавая замыкание
    StartCoroutine(WaitAndDo(() => {
        Debug.Log(this.transform.position); // Захватывает 'this'
    }));
}

Memory Profiler (пакет из Package Manager) — для детального анализа:

  • Сравнение снимков памяти (Take Snapshot)
  • Анализ Memory Roots — цепочек ссылок, удерживающих объекты
  • Поиск Unused Assets — ресурсов в памяти, но не используемых на сцене

Типичные источники утечек

События и делегаты — наиболее частые виновники:

// Утечка через неправильную отписку от событий
void OnEnable() {
    GameManager.OnLevelComplete += HandleComplete;
}

void OnDisable() {
    GameManager.OnLevelComplete -= HandleComplete; // Важно!
}

// Проблема статических событий
public static event Action OnGameEvent; // Удерживает ссылки на подписчиков

Кеширование и статические ссылки:

public class TextureCache {
    private static Dictionary<string, Texture> _cache = new();
    // Текстуры никогда не выгружаются без явного очищения
}

Невыгружаемые ресурсы:

  • Resources.Load без последующего Resources.UnloadUnusedAssets
  • Объекты в DontDestroyOnLoad, накапливающие состояние
  • AssetBundle без вызова Unload(true)

Практическая методика поиска

  1. Воспроизведение сценария — создаю повторяемый цикл (загрузка уровня → игра → выход)
  2. Снимки "до/после" — делаю снимки памяти в Profiler в ключевых точках
  3. Анализ различий — ищу объекты, количество которых монотонно растет
  4. Поиск корневых ссылок — определяю, что удерживает объекты в памяти

Профилактические меры

Паттерны предотвращения утечек:

  • Использую WeakReference для кешей, которые могут быть выгружены
  • Реализую IDisposable для классов, управляющих внешними ресурсами
  • Применяю Object Pooling для часто создаваемых/уничтожаемых объектов

Инструментарий для автоматизации:

// Кастомный валидатор для проверки подписок на события
#if UNITY_EDITOR
[InitializeOnLoad]
public static class EventLeakDetector {
    static EventLeakDetector() {
        EditorApplication.playModeStateChanged += state => {
            if (state == PlayModeStateChange.ExitingPlayMode) {
                ValidateEventSubscriptions();
            }
        };
    }
}
#endif

Особые случаи платформ

  • iOS/Android — уделяю особое внимание Texture Memory, так как мобильные GPU имеют ограниченную память
  • WebGL — контролирую общий размер Heap, так как браузеры имеют строгие ограничения
  • Консоли — анализирую память в течение длительных игровых сессий (10+ часов)

Ключевые метрики для мониторинга

  • Total Allocated — не должен расти бесконечно
  • Garbage Collector frequency — частые сборки мусора указывают на проблемы с аллокациями
  • Texture Memory — особенно важна для мобильных платформ
  • Managed Heap Size — рост без возврата к базовому уровню

Поиск утечек — это не разовая операция, а часть регулярного цикла разработки. Я интегрирую проверки памяти в CI/CD pipeline, где автоматически запускаются тестовые сценарии с последующим анализом отчетов Profiler. Это позволяет обнаруживать проблемы до того, как они попадут в продакшен.

Как находишь утечки памяти? | PrepBro