Неуправляемая память C#
Неуправляемый слой памяти C# позволяет получить доступ к слою основной памяти для точной настройки распределения памяти, с удобством написания кода C#.
Для доступа к неуправляемой памяти C# можно использовать пространство имён Unity.Collections, включая NativeArray, в основном API Unity и структуры данных из пакета Unity Collections. При использовании системы заданий Unity или Burst необходимо работать с неуправляемой памятью C#.
Обзор выделяющих памяти для основных контейнеров
UnityБиблиотеки собственного кода отслеживают использование собственной памяти через систему меток памяти, областей и корней, которые управляются Unity’s нативный менеджер памяти. Profiler использует менеджер памяти для мониторинга использования памяти. Сборщик мусора ассетов также отслеживает типы, которые наследуют от UnityEngine.Object так что на вызовах к Resources.UnloadUnusedAssets он может очистить память, выделенную для ассетов, которые больше не упоминаются.
Нативный диспетчер памяти Unity использует метки памяти, чтобы классифицировать её использование и выбирать, какой Allocator будет выделять память. Распределитель, используемый диспетчером памяти для каждой метки, зависит от платформы. Собственные именованные метки памяти можно создавать с помощью MemoryLabel API. Важно: API MemoryLabel несовместим с пакетом Collections.
Менеджер памяти использует области для категоризации использования памяти для целей профилирования. Он использует корни для отслеживания связанных выделений памяти под одним корнем. Например, собственная память для каждого типа, наследующего от UnityEngine.Object, имеет корень в области, называемой Object. Когда объект удаляется, например, через Resources.UnloadUnusedAssets, все выделения, связанные с корнем этого объекта, также высвобождаются.
Вы можете использовать пакет Пакет Memory Profiler для проверки использования памяти по меткам памяти, областям и корням. Это включает любые пользовательские метки, которые вы определили с помощью MemoryLabel. Вы также можете обнаружить базовый распределитель, который выделил память по именам регионов.
Типы распределителей
Вы можете использовать некоторые нативные Типы распределителей с нативными типами контейнеров Unity.Collections пространство имен. Таким образом доступны следующие типы распределителей:
Temp: тип временного распределителя для краткосрочных распределений.TempJob: Тип временного распределителя для более долгосрочных распределений, передаваемых от задания к заданию.Persistent: Распределитель без каких-либо временных ограничений.AudioKernel: Распределитель для DSP распределений аудио ядра.Domain: Распределитель, который действует в течение всего срока жизни домена.
Чтобы использовать эти типы, передайте Allocator значение перечисления, чтобы выбрать метку памяти нужного типа нативного аллокатора. Как вариант, для низкоуровневых выделений, где нужна собственная категоризация, можно создать и передать MemoryLabel если выбранная функция не является функцией распределения, Temp распределитель заполнен, Unity выбирает резервный распределитель (обычно TempJob, или Температурный перелив).
Темп
Temp — это тип временного распределителя Unity. Он предназначен для небольших кратковременных распределений, которые не могут пересекать границу кадра, таких как временные распределения, сделанные в рамках одного задания. Тип Temp — это распределитель стека для небольших объемов памяти, которые Unity выделяет из основного пула памяти.
Существует множество распределителей Temp, и каждый поток, который нуждается в распределителе, имеет один. Unity перезагружает распределители Temp каждый кадр, обеспечивая чистую схему использования памяти. Однако, если память переливается в резервные распределители, их память может быть фрагментирована.
Вы можете использовать Profiler.GetTempAllocatorSize и Profiler.SetTempAllocatorRequestedSize для получения и установки размера распределителей Temp.
Размеры для распределителя Temp по умолчанию:
- Редактор: 16 MB основных потоков, 256 KB рабочих потоков.
- Игроки: 4 MB основных потока, 256 KB рабочих потоков.
Если эти размеры превышаются, выделения на основном потоке возвращаются к TempJob В других потоках они возвращаются к распределителю Temp Overflow. Дополнительные сведения о временных собственных распределениях см. в разделе Хранение потока локально (TLS) распределитель документация.
TempJob
Этот тип использует распределитель линейного стиля, который Unity хранит в области TempJob, которую он выделяет из основной памяти. Он предназначен для более крупных временных распределений, которые передаются от задания к заданию, и тех, которые могут переносить данные между кадрами. Если распределения не удаляются в течение 4 кадров после их создания, в Unity Editor отображается предупреждение.
Примечание: Если доступная память исчерпана, Unity делает выделения overspill в основной памяти (malloc). Большинство платформ могут иметь до 64 MB памяти TempJob, но на меньших системах памяти этот предел может быть как низкий как 16 MB.
Если этот распределитель заполнен, распределение возвращается к Temp Job Overflow Allocator. Дополнительные сведения о временном распределении заданий см. в документации по потоково-безопасному линейному распределителю.
Постоянный
Этот распределитель выделяет память без ограничений по времени, ограничивается только количеством свободной памяти на устройстве, и поэтому не имеет резерва. Он может существовать так долго, как вам это нужно, но это также означает, что только DisposeSentinel класс предупреждает вас, если выделенная память не была освобождена, — но только когда ваш дескриптор этой памяти был собран сборщиком мусора. Выделение постоянной памяти медленнее, чем временной.
Дополнительные ресурсы
- Пакет коллекций
- Память в Unity введение