Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Приложения WinUI, созданные с помощью пакета SDK для приложений Windows и написанные на C#, получают автоматическое управление памятью от сборщика мусора .NET. В этой статье приведены рекомендации по поведению и производительности сборщика мусора .NET в приложениях WinUI. Дополнительные сведения о работе сборщика мусора .NET и средствах для отладки и анализа производительности сборщика мусора см. в статье "Сборка мусора".
Замечание
Необходимость вмешаться в поведение сборщика мусора по умолчанию свидетельствует о общих проблемах с памятью в приложении. Используйте средство использования памяти в Visual Studio, а также руководство по сборке мусора и производительности для идентификации объектов, которые выжили в коллекциях.
Сборщик мусора определяет момент запуска, балансируя потребление памяти управляемой кучи с объемом работы, которую необходимо выполнить сборщику мусора. Одним из способов того, как сборщик мусора делает это, разделив кучу на поколения и собирая только часть кучи большую часть времени. Существуют три поколения в управляемой куче:
- Поколение 0. Это поколение содержит только что выделенные объекты, если они не имеют 85 КБ или больше, в этом случае они являются частью большой кучи объектов. Большая куча объектов собирается с коллекциями поколения 2. Коллекции поколения 0 — это наиболее часто встречающийся тип коллекции и очистка краткосрочных объектов, таких как локальные переменные.
- Поколение 1. Это поколение содержит объекты, которые пережили коллекции поколения 0. Он служит буфером между поколением 0 и поколением 2. Коллекции поколения 1 происходят реже, чем коллекции поколения 0 и очищают временные объекты, активные в предыдущих коллекциях поколения 0. Коллекция поколения 1 также собирает поколение 0.
- Поколение 2. Это поколение содержит долгоживущие объекты, которые пережили коллекции поколения 0 и поколения 1. Коллекции поколения 2 являются наименее частыми и собирают всю управляемую кучу, в том числе большую кучу объектов, которая содержит объекты размером 85 КБ или больше.
Производительность сборщика мусора можно измерять двумя аспектами: время, необходимое для сборки мусора, а также потребление памяти управляемой кучи. Если у вас есть небольшое приложение с размером кучи менее 100 МБ, то сосредоточьтесь на снижении потребления памяти. Если у вас есть приложение с управляемой кучей размером более 100 МБ, то сосредоточьтесь только на сокращении времени сборки мусора. Вот как можно помочь сборщику мусора .NET повысить производительность.
Уменьшение потребления памяти
Ссылки на выпуск
Ссылка на объект в приложении предотвращает сбор этого объекта и всех объектов, на которые он ссылается. Компилятор .NET хорошо определяет, когда переменная больше не используется, поэтому объекты, удерживаемые этой переменной, будут иметь право на коллекцию. Но в некоторых случаях может быть не очевидно, что некоторые объекты имеют ссылку на другие объекты, так как часть графа объектов может принадлежать библиотекам, которые использует ваше приложение. Дополнительные сведения о средствах и методах для получения сведений о том, какие объекты выживают в сборке мусора, см. в статье "Сборка мусора" и производительность.
Вызвать сборку мусора, если это полезно
Выполняйте сборку мусора только после того, как вы измерили производительность приложения и определили, что вызов сборки улучшит её производительность.
Вы можете инициировать сборку мусора для поколения, выполнив GC.Collect(n), где n — это поколение, которое вы хотите собрать (0, 1 или 2).
Замечание
Рекомендуется не принудительно использовать сборку мусора в приложении, так как сборщик мусора использует множество эвристических средств, чтобы определить лучшее время для выполнения коллекции, и принудительное использование коллекции во многих случаях является ненужным использованием ЦП. Но если вы знаете, что у вас есть большое количество объектов в приложении, которые больше не используются, и хотите вернуть эту память системе, может потребоваться принудительный запуск сбора мусора. Например, вы можете вызвать коллекцию в конце последовательности загрузки в игре, чтобы освободить память до начала игрового процесса. Чтобы избежать непреднамеренного слишком частого вызова сборщика мусора, можно установить для GCCollectionMode режим Optimized. Это указывает сборщику мусора начинать сбор только в том случае, если сборщик определяет, что сбор будет достаточно продуктивным, чтобы быть оправданным.
Сокращение времени сборки мусора
Этот раздел применяется, если вы проанализировали приложение и наблюдали длительное время работы сборщика мусора. Время пауз, связанных со сборкой мусора, включает время, необходимое для выполнения единого прохода сборки мусора, и общее время, которое ваше приложение тратит на выполнение сборок мусора. Время, необходимое для сбора, зависит от того, сколько динамических данных сборщик должен анализировать. Поколение 0 и поколение 1 имеют ограниченный размер, но поколение 2 продолжает расти, поскольку объекты с длительным сроком жизни остаются активными в приложении. Это означает, что время сбора для поколения 0 и поколения 1 привязано, а коллекции поколения 2 могут занять больше времени. Частота выполнения сборок мусора в основном зависит от количества выделяемой памяти, поскольку сборка мусора освобождает память для удовлетворения запросов на выделение новой памяти.
Сборщик мусора иногда приостанавливает работу приложения, но не обязательно на весь период выполнения сборки. Время приостановки обычно не является понятным для пользователя в приложении, особенно для коллекций поколения 0 и поколения 1. Функция фоновой сборки мусора .NET позволяет параллельно выполнять сборки второго поколения во время работы вашего приложения, приостанавливая его лишь на короткое время. Но не всегда можно сделать коллекцию поколения 2 как фоновую коллекцию. В этом случае пауза может быть ощущаемой пользователем, если у вас достаточно большая куча памяти (более 100 Мбайт).
Частые сборки мусора могут способствовать увеличению потребления ЦП, увеличению потребления энергии, увеличению времени загрузки или снижению частоты кадров в приложении. Ниже приведены некоторые методы, которые можно использовать для уменьшения времени сборки мусора и приостановки сбора в управляемом приложении WinUI.
Сократите выделение памяти
Если вы не выделяете объекты, сборщик мусора не выполняется, если только в системе не возникнет состояние недостатка памяти. Уменьшение объема памяти, которую вы выделяете напрямую, приводит к более редким сборкам мусора.
Если в некоторых разделах приложения паузы полностью нежелательны, вы можете заранее выделить необходимые объекты в течение менее критического времени производительности. Например, игра может выделить все объекты, необходимые для игрового процесса во время загрузки экрана уровня, и не делать выделения во время игрового процесса. Это позволяет избежать пауз, пока пользователь играет в игру, и может привести к более высокой и более согласованной частоте кадров.
Уменьшение коллекций поколения 2 путем предотвращения создания объектов со средним временем существования
Сборщики мусора поколений лучше всего работают, если в приложении существуют короткоживущие и/или долгодействующие объекты. Кратковременные объекты собираются в более дешевых коллекциях поколения 0 и поколения 1, а объекты, которые существуют дольше, переносятся в поколение 2, которое собирается редко. Долгоживущие объекты — это объекты, которые используются в течение всего периода работы приложения или в течение значительного периода приложения, например на определенном уровне страницы или игры.
Если вы часто создаете объекты с временным сроком существования, но они живут достаточно долго, чтобы быть повышены до второго поколения, происходит больше затратных сборок второго поколения. Вы можете уменьшить коллекцию поколения 2 путем повторной переработки существующих объектов или более быстрого освобождения объектов.
Распространенный пример объектов со средним временем существования — это объекты, используемые для отображения элементов в списке, который прокручивает пользователь. Если объекты создаются, когда элементы в списке становятся видимыми при прокрутке, и перестают использоваться, когда элементы исчезают из поля зрения, то в вашем приложении обычно наблюдается большое количество сборок второго поколения. В таких ситуациях можно предварительно выделить и повторно использовать набор объектов для активно отображаемых пользователю данных, и использовать временные объекты для загрузки информации по мере появления элементов в списке.
Сокращение коллекций поколения 2 путем предотвращения больших размеров объектов с коротким временем существования
Любой объект, размер которого составляет 85 КБ и более, размещается на куче больших объектов (LOH) и собирается в составе поколения 2. Если у вас есть временные переменные, такие как буферы, которые больше 85 КБ, то коллекция поколения 2 очищает их. Ограничение временных переменных менее 85 КБ уменьшает количество коллекций поколения 2 в приложении. Одним из распространенных способов является создание буферного пула и повторное использование объектов из пула, чтобы избежать больших временных выделений.
Избегайте объектов с множеством ссылок
Сборщик мусора определяет, какие объекты являются активными, следуя ссылкам между ними, начиная с корней в вашем приложении. Дополнительные сведения см. в разделе "Что происходит во время сборки мусора". Если объект содержит много ссылок, то для сборщика мусора требуется больше работы. Распространенный метод, особенно с большими объектами, заключается в преобразовании ссылочных объектов в объекты без ссылок. Например, вместо хранения ссылки сохраните индекс. Конечно, этот метод работает только тогда, когда это логически возможно.
Замена ссылок на объекты индексами может быть разрушительным и сложным изменением приложения и наиболее эффективным для больших объектов с большим количеством ссылок. Делайте это только в том случае, если вы замечаете, что сборка мусора в вашем приложении занимает много времени из-за объектов с большим количеством ссылок.
Windows developer