Unity 6.3
0 онлайн 96 гостей 3 в системе
Вход
Оптимизация Шаг 7 из 208

Режимы сбора мусора

мусоросборник Unity имеет следующие режимы:

  • Инкрементальная уборка мусора: Включена по умолчанию. Этот режим распределяет процесс сборки мусора на несколько кадров.
  • Неинкрементальный режим сбора мусора: Если вы отключите Инкрементальный GC Настройка Проигрывателя (Project Настройки > Проигрыватель > Конфигурация), сборщик мусора прекращает запуск вашего приложения для проверки и обработки объектов на куче. Этот режим также известен как сбор мусора с остановкой мира.
  • Ручное удаление мусора: Используйте GarbageCollector.GCMode API, чтобы полностью контролировать, когда Unity запускает сборщик мусора.

Информацию об использовании каждого из режимов сбора мусора см. в Настройка сбора мусора.

Интенсивный сбор мусора

Инкрементальная сборка мусора распределяет процесс сборки мусора на несколько кадров. Это поведение сборки мусора по умолчанию в Unity.

Сборщик мусора Unity использует сборщик мусора Boehm-Demers-Weiser. По умолчанию Unity использует его в инкрементальном режиме, что означает, что сборщик мусора разделяет свою рабочую нагрузку на несколько кадров и делает более короткие перерывы в выполнении приложения.

В неинкрементном режиме Unity останавливает основной поток CPU на одну продолжительную паузу (сборка мусора с полной остановкой выполнения), чтобы обработать все объекты в управляемой куче.

Инкрементальный режим не делает сбор мусора быстрее, но потому что он распределяет рабочую нагрузку по нескольким кадрам, пики производительности, связанные с сбором мусора, уменьшаются. GC шпильки потому что они появляются как большие шипики в Profiler окна график времени кадра.

Важно: Веб-платформа не поддерживает инкрементальный сбор мусора. Дополнительные сведения см. в Соображения по памяти в сборе мусора.

Пример постепенной сборки мусора

Следующие скриншоты из Profiler иллюстрируют, как постепенное удаление мусора уменьшает проблемы с частотой кадров:

Сеанс профилирования с включенной функцией Incremental GC
Сеанс профилирования с включенной функцией Incremental GC
Сеанс профилирования с отключенным приростным GC
Сеанс профилирования с отключенным приростным GC

В верхней сессии профилирования включена настройка Incremental GC. Приложение имеет постоянную частоту кадров 60 fps, потому что сборщик мусора распределяет операцию сбора мусора на несколько кадров. Сборщик мусора использует небольшой временной отрезок каждого кадра, обозначенный темно-зелёной полосой прямо над желтым следом VSync.

В нижней сессии профилирования отключена настройка Incremental GC, и видно пиковое значение GC. Пиковое значение GC прерывает постоянную частоту кадров 60 кадров в секунду и выталкивает кадр, в котором происходит сбор мусора, за предел 16 мс, необходимый для поддержания частоты 60 кадров в секунду.

Если ваше приложение использует VSync или Application.targetFrameRate, Unity корректирует время, выделяемое на сбор мусора, на основе оставшегося доступного времени кадра. Таким образом, Unity может запустить сборщик мусора во время ожидания, и может выполнять сбор мусора с минимальным влиянием на производительность.

Примечание: Если вы установите VSync Количество на любое другое значение, кроме Don't Sync (в настройках качества проекта или со свойством Application.VSync), или включите свойство Application.targetFrameRate, Unity автоматически использует любое время простоя, оставшееся в конце данного кадра для постепенного удаления мусора.

Чтобы получить более точный контроль над поведением приростного сбора мусора, вы можете использовать Scripting.GarbageCollector класс. Например, если вы не хотите использовать VSync или целевую частоту кадров, можно вычислить, сколько времени остаётся до конца кадра, и отдать это время сборщику мусора.

Дополнительные сведения см. в Настройка сбора мусора.

Неинкрементальный режим сбора мусора

Инкрементальная сборка мусора может быть проблематичной для приложения, потому что, когда сборщик мусора разделяет свою работу в этом режиме, он также разделяет фазу маркировки. Фаза маркировки — это фаза, в которой сборщик мусора сканирует все управляемые объекты, чтобы определить, какие объекты все еще используются и какие объекты можно очистить.

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

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

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

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

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

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

Чтобы отключить приростную сборку мусора, см. Настройка сборки мусора.

Сборка мусора вручную

Вы можете использовать GarbageCollector.GCMode API для отключения сбора мусора во время выполнения. Это предотвращает пики CPU, но использование памяти вашим приложением никогда не уменьшается, потому что сборщик мусора не собирает объекты, которые больше не имеют никаких ссылок.

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

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

Например, вы можете выделить всю память, необходимую для уровня вашей игры, до его загрузки, а затем отключить сборщик мусора, чтобы избежать дополнительных затрат на производительность во время уровня. После завершения уровня и высвобождения всей памяти вы можете снова включить сборщик мусора и использовать System.GC.Collect для восстановления памяти перед загрузкой следующего уровня.

Дополнительные сведения о включении и отключении сбора мусора во время выполнения см. в Настройка сбора мусора.

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