Unity 6.3
0 онлайн 20 гостей 3 в системе
Вход

Введение управляемой памяти

Система управляемой памяти Unity является частью среды скриптов C#, предоставляемой либо Виртуальные машины Mono или IL2CPP (VM). Достоинство системы управляемой памяти в том, что она сама освобождает память, и вам не нужно запрашивать освобождение вручную из кода. Эта виртуальная память создаёт контролируемое окружение, состоящее из следующих частей:

  • Управляемая куча: Секция памяти, которую VM автоматически контролирует с мусорщик. Память, выделенная на управляемом стеке, называется GC Ассигнования, и Profiler регистрирует любое возникновение такого распределения как GC.Alloc образец.
  • Скриптовый стек: Область памяти фиксированного размера, выделяемая в начале каждого потока. Она отслеживает временные данные, такие как переменные и поток выполнения, когда приложение перемещается в блоки кода и из них.
  • Внутренняя память VM: Содержит память, связанную с исполнением и управлением Unity скриптов VM. Вы не имеете прямого доступа к ней и нормальное выполнение вашего кода влияет на нее косвенно. Полезно знать, что она включает память, связанную с исполняемым кодом, который генерирует ваш код, в частности память, используемую для generics, тип метаданных, используемых для отражение, и память, необходимую для запуска VM.

Автоматическое управление памятью

UnityСистема управляемой памяти использует мусорщик и управляемый стек для автоматического высвобождения выделений памяти, когда ваши скрипты больше не содержат никаких ссылок на эти выделения. Это помогает защитить от утечек памяти, которые происходят, когда выделенная память никогда не высвобождается, потому что ссылка, необходимая для ее высвобождения вручную, была потеряна.

Система управления памятью Unity защищает доступ к памяти, что означает, что вы не можете получить доступ к памяти, которая была освобождена или никогда не была доступна для вашего кода. Тем не менее, этот процесс управления памятью влияет на производительность во время выполнения, потому что выделение управляемой памяти занимает много времени для CPU. Garbage collection может также остановить CPU от выполнения другой работы до завершения.

На следующей диаграмме синий квадратик представляет количество памяти, которое Unity выделяет управляемой куче. Белые квадратики внутри него представляют значения данных, которые Unity хранит в пространстве памяти управляемой кучи. Когда требуются дополнительные значения данных, Unity выделяет им свободное пространство из управляемой кучи (аннотированное A).

Количество памяти. Пометка A на диаграмме означает некоторую свободную память.
Количество памяти. Пометка A на диаграмме означает некоторую свободную память.

Примечание: объём виртуальной памяти в управляемой куче во время выполнения может только расти. Рост потребления виртуальной памяти не всегда вызывает рост потребления физической памяти.

Управляемая структура кучи

Управляемая куча обращается к виртуальной памяти следующими единицами:

  • Страница: Измерение физической памяти, используемой операционной системой. Обычно 4 КБ на Windows и macOS, или 16 КБ на мобильных устройствах.
  • Сегмент (блок стека): Содержит по крайней мере одну страницу, объект или комбинацию обоих. Используется сборщиком мусора Unity для выделения, маркировки и очистки памяти.

Для получения дополнительной информации о мусорном контейнере Unity, см. Обзор мусорного контейнера

Чистые и грязные страницы

Когда страница поступает в физическую память, операционная система отслеживает, изменило ли ее приложение, и присваивает странице один из следующих типов:

Тип страницы Описание Влияние на результаты деятельности
Чистый Содержит данные, которые были прочитаны из файла и не были изменены. Например, исполняемый код игры, данные только для чтения или текстуры. Если у OS не хватает памяти, он может безопасно отбросить чистую страницу, потому что он всегда может перезагрузить страницу из оригинального файла на диске. Незначительное влияние на стабильность приложения.
Грязные Содержит данные, измененные вашим приложением. Данные на грязной странице отличаются от исходных данных на диске. Это означает, что OS не может отбросить страницу без сохранения данных грязной страницы. Высокая нагрузка на память и основная причина сбоев из-за отсутствия памяти (OOM).

Примечание: Когда сборщик мусора помечает грязную страницу как повторяющуюся, OS все равно распознает страницу как грязную, потому что она содержит измененные данные. Это может означать, что система управления памятью обозначает страницу как грязную, даже если сборщик мусора отметил ее как повторяющуюся. Для получения дополнительной информации о сборе мусора, см. Введение в сборщик мусора.

Типы, выделенные управляемой куче

При вызове метода, скриптовый backend копирует значения его параметров в область памяти, зарезервированную для этого конкретного вызова, в структуре данных, называемой стек вызова. Скриптовый backend может быстро копировать типы данных, которые занимают несколько байт. Однако объекты, строки и массивы обычно намного больше, и для скриптового backend неэффективно копировать эти типы данных на регулярной основе.

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

Важно что вы знакомы с типами значения и ссылки, так, что вы можете эффективно управлять вашим кодом. Для больше информации, обратитесь к документации Майкрософта на типы значений, и типы справочных данных.

Фрагментация памяти и управляемое расширение кучи

Когда Unity освобождает объект, память, которую занимал объект, высвобождается. Однако свободное пространство не становится частью одного большого пула свободной памяти.

Объекты по обе стороны освобождаемого объекта могут все еще использоваться. Из-за этого освобожденное пространство является пробелом между другими сегментами памяти. Unity может использовать этот пробел только для хранения данных равного или меньшего размера, чем освобожденный объект. Эта ситуация называется фрагментацией памяти, и следующая диаграмма показывает пример этого:

Количество памяти, с некоторыми освобожденными объектами, представленными серыми пунктирными линиями.
Количество памяти, с некоторыми освобожденными объектами, представленными серыми пунктирными линиями.

Фрагментация памяти происходит, когда в куче имеется большое количество памяти, но она доступна только в промежутках памяти между объектами. Несмотря на то, что общего пространства достаточно для большого выделения памяти, управляемый куча не может найти достаточно большой одиночный блок непрерывной памяти для назначения выделения.

Если выделяется большой объект и для его размещения не хватает свободного свободного пространства, менеджер памяти Unity выполняет две операции:

  1. Сборщик мусора запускается, если он еще не сделал этого. Это попытка высвободить достаточно места для выполнения запроса на выделение.
  2. Если после запуска сборщика мусора все еще не хватает непрерывного пространства для размещения запрошенного количества памяти, куча должна расшириться. Конкретное количество, которое куча расширяет, зависит от платформы. На большинстве платформ, когда куча расширяется, она расширяется в два раза больше, чем предыдущее расширение. Если размер запрошенного выделения больше, чем это, Unity выполняет внецикловое расширение, чтобы поместить это выделение и продолжить с предыдущего регулярного размера расширения в качестве основы для следующего расширения.

Unity не высвобождает память, выделенную для управляемого кучи, когда она регулярно расширяется. Вместо этого, она сохраняет расширенный кучу, даже если большая часть кучи пуста. Это исключает необходимость повторного расширения кучи, если в дальнейшем происходят большие выделения.

На большинстве платформ, Unity в конечном итоге высвобождает память, которую используют пустые части управляемого стека обратно в операционную систему. Интервал, в котором это происходит, не гарантирован и ненадежен. Это требует, чтобы эти части состояли из одной или нескольких полных страниц памяти (4 KB на большинстве платформ).

Управляемая куча и собственная память

Сборщик мусора не очищает объекты памяти , объекты памяти или другие объекты памяти. Unity очищает память только в следующих ситуациях:

  • При вызове Resources.UnloadUnusedAssets. Вы можете вручную вызвать UnloadUnusedAssets, или Unity вызывает его автоматически при разгрузке сцены из-за загрузки новой сцены в LoadSceneMode.Single. Для асинхронной разгрузки сцены вы можете запросить ассеты, которые были динамически созданы и встроены в сцену во время сборки с параметрами SceneManager.UnloadSceneAsync и опцией UnloadSceneOptions.UnloadAllEmbeddedSceneObjects. Вызов SceneManager.UnloadSceneAsync с UnloadSceneOptions.UnloadAllEmbeddedSceneObjects не разгружает обычные ассеты, которые Unity загрузил для использования в сцене, или динамически и во время выполнения созданные ассеты.
  • Когда Destroy вызвана для объекта.

Resources.UnloadUnusedAssets выгружает все нативные объекты, которые больше не имеют никаких ссылок, указывающих на них. Если вы хотите освободить память раньше, например, если у вас есть полноэкранные экземпляры RenderTexture на платформах с низким RAM, вызовите Destroy на объектах.

Если вы хотите иметь больше контроля над ресурсами, которые остаются в памяти, используйте , AssetBundles, и Addressables.

Важно: Вызов UnloadUnusedAssets или GC.Collect является CPU-интенсивным процессом. В больших проектах завершение может занять несколько секунд

Перед вызовом UnloadUnusedAssets, убедитесь, что вы не держите управляемые ссылки на основные объекты, которые вы хотите очистить, или основные объекты не будут загружены. Статические поля и события являются общими способами удержания этих объектов без намерения. Дополнительные сведения о том, как анализировать эти проблемы с Memory Profiler, см. Управляемые объекты оболочки в памяти Profiler документация пакета.

Дополнительные ресурсы