Язык программирования C#9 и платформа .NET5
Шрифт:
На заметку! Строго говоря, сборщик мусора использует две отдельные кучи, одна из которых предназначена специально для хранения крупных объектов. Во время сборки мусора обращение к данной куче производится менее часто из-за возможного снижения производительности, связанного с перемещением больших объектов. В .NET Core куча для хранения крупных объектов может быть уплотнена по запросу или при достижении необязательных жестких границ, устанавливающих абсолютную или процентную степень использования памяти.
Понятие поколений объектов
Когда
Для содействия оптимизации процесса каждому объекту в куче назначается специфичное "поколение". Лежащая в основе поколений идея проста: чем дольше объект существует в куче, тем выше вероятность того, что он там будет оставаться. Например, класс, который определяет главное окно настольного приложения, будет находиться в памяти вплоть до завершения приложения. С другой стороны объекты, которые были помещены в кучу только недавно (такие как объект, размещенный внутри области действия метода), по всей видимости, довольно быстро станут недостижимыми. Исходя из таких предположений, каждый объект в куче принадлежит совокупности одного из перечисленных ниже поколений.
• Поколение 0. Идентифицирует новый размещенный в памяти объект, который еще никогда не помечался как подлежащий сборке мусора (за исключением крупных объектов, изначально помещаемых в совокупность поколения 2). Большинство объектов утилизируются сборщиком мусора в поколении 0 и не доживают до поколения 1.
• Поколение 1. Идентифицирует объект, который уже пережил одну сборку мусора. Это поколение также служит буфером между кратко и длительно существующими объектами.
• Поколение 2. Идентифицирует объект, которому удалось пережить более одной очистки сборщиком мусора, или весьма крупный объект, появившийся в совокупности поколения 2.
На заметку! Поколения 0 и 1 называются эфемерными (недолговечными). В следующем разделе будет показано, что процесс сборки мусора трактует эфемерные поколения по-разному.
Сначала сборщик мусора исследует все объекты, относящиеся к поколению 0. Если пометка и удаление (или освобождение) таких объектов в результате обеспечивают требуемый объем свободной памяти, то любые уцелевшие объекты повышаются до поколения 1. Чтобы увидеть, каким образом поколение объекта влияет на процесс сборки мусора, взгляните на рис. 9.5, где схематически показано, как набор уцелевших объектов поколения 0 (А, В и E) повышается до следующего поколения после восстановления требуемого объема памяти.
Если все объекты поколения 0 проверены, но по-прежнему требуется дополнительная память, тогда начинают исследоваться на предмет достижимости и подвергаться сборке мусора объекты поколения 1. Уцелевшие объекты поколения 1 повышаются до поколения 2. Если же сборщику мусора все еще требуется дополнительная память, то начинают проверяться объекты поколения 2. На этом этапе объекты поколения 2, которым удается пережить сборку мусора, остаются объектами того же поколения 2, учитывая заранее определенный верхний предел поколений объектов.
В заключение следует отметить, что за счет назначения объектам в куче определенного поколения более новые объекты (такие как локальные переменные) будут удаляться быстрее, в то время как более старые (наподобие главного окна приложения) будут существовать дольше.
Сборка мусора инициируется, когда в системе оказывается мало физической памяти, когда объем памяти, выделенной в физической куче, превышает приемлемый порог или когда в коде приложения
вызывается методЕсли все описанное выглядит слегка удивительным и более совершенным, чем необходимость в самостоятельном управлении памятью, тогда имейте в виду, что процесс сборки мусора не обходится без определенных затрат. Время сборки мусора и то, что будет подвергаться сборке, обычно не находится под контролем разработчиков, хотя сборка мусора безусловно может расцениваться положительно или отрицательно. Кроме того, выполнение сборки мусора приводит к расходу циклов центрального процессора (ЦП) и может повлиять на производительность приложения. В последующих разделах исследуются различные типы сборки мусора.
Эфемерные поколения и сегменты
Как упоминалось ранее, поколения 0 и 1 существуют недолго и называются эфемерными поколениями. Эти поколения размещаются в памяти, которая известна как эфемерный сегмент. Когда происходит сборка мусора, запрошенные сборщиком мусора новые сегменты становятся новыми эфемерными сегментами, а сегменты, содержащие объекты, которые уцелели в прошедшем поколении 1, образуют новый сегмент поколения 2. Размер эфемерного сегмента зависит от ряда факторов, таких как тип сборки мусора (рассматривается следующим) и разрядность системы. Размеры эфемерных сегментов описаны в табл. 9.1.
Типы сборки мусора
Исполняющая среда поддерживает два описанных ниже типа сборки мусора.
• Сборка мусора на рабочей станции. Тип сборки мусора, который спроектирован для клиентских приложений и является стандартным для автономных приложений. Сборка мусора на рабочей станции может быть фоновой (обсуждается ниже) или выполняться в непараллельном режиме.
• Сборка мусора на сервере. Тип сборки мусора, спроектированный для серверных приложений, которым требуется высокая производительность и масштабируемость. Подобно сборке мусора на рабочей станции сборка мусора на сервере может быть фоновой или выполняться в непараллельном режиме.
На заметку! Названия служат признаком стандартных настроек для приложений рабочей станции и сервера, но метод сборки мусора можно настраивать через файл
Сборка мусора на рабочей станции производится в том же потоке, где она была инициирована, и сохраняет тот же самый приоритет, который был назначен во время запуска. Это может привести к состязанию с другими потоками в приложении.
Сборка мусора на сервере осуществляется в нескольких выделенных потоках, которым назначен уровень приоритета
Фоновая сборка мусора
Начиная с версии .NET 4.0 и продолжая в .NET Core, сборщик мусора способен решать вопрос с приостановкой потоков при очистке объектов в управляемой куче, используя фоновую сборку мусора. Несмотря на название приема, это вовсе не означает, что вся сборка мусора теперь происходит в дополнительных фоновых потоках выполнения. На самом деле, если фоновая сборка мусора производится для объектов, принадлежащих к неэфемерному поколению, то исполняющая среда .NET Core может выполнять сборку мусора в отношении объектов эфемерных поколений внутри отдельного фонового потока.