Язык программирования C#9 и платформа .NET5
Сборка мусора на рабочей станции производится в том же потоке, где она была инициирована, и сохраняет тот же самый приоритет, который был назначен во время запуска. Это может привести к состязанию с другими потоками в приложении.
Сборка мусора на сервере осуществляется в нескольких выделенных потоках, которым назначен уровень приоритета
(тема многопоточности раскрывается в главе 15). Для выполнения сборки мусора каждый ЦП получает выделенную кучу и отдельный поток. В итоге сборка мусора на сервере может стать крайне ресурсоемкой.THREAD_PRIORITY_HIGHESTФоновая сборка мусора
Начиная с версии .NET 4.0 и продолжая в .NET Core, сборщик мусора способен решать вопрос с приостановкой потоков при очистке объектов в управляемой куче, используя фоновую сборку мусора. Несмотря на название приема, это вовсе не означает, что вся сборка мусора теперь происходит в дополнительных фоновых потоках выполнения. На самом деле, если фоновая сборка мусора производится для объектов, принадлежащих к неэфемерному поколению, то исполняющая среда .NET Core может выполнять сборку мусора в отношении объектов эфемерных поколений внутри отдельного фонового потока.
В качестве связанного замечания: механизм сборки мусора в .NET 4.0 и последующих версиях был усовершенствован с целью дальнейшего сокращения времени приостановки заданного потока, которая связана со сборкой мусора. Конечным результатом таких изменений стало то, что процесс очистки неиспользуемых объектов поколения 0 или поколения 1 был оптимизирован и позволяет обеспечить более высокую производительность приложений (что действительно важно для систем реального времени, которые требуют небольших и предсказуемых перерывов на сборку мусора).
Тем не менее, важно понимать, что ввод новой модели сборки мусора совершенно не повлиял на способ построения приложений .NET Core. С практической точки зрения вы можете просто разрешить сборщику мусора выполнять свою работу без непосредственного вмешательства с вашей стороны (и радоваться тому, что разработчики в Microsoft продолжают улучшать процесс сборки мусора в прозрачной манере).
Тип System.GC
В сборке
предоставляется класс по имениmscorlib.dll, который позволяет программно взаимодействовать со сборщиком мусора, применяя набор статических членов. Имейте в виду, что необходимость в прямом взаимодействии с классомSystem.GCвнутри разрабатываемого кода возникает редко (если вообще возникает). Обычно единственной ситуацией, когда будут использоваться членыSystem.GC, является создание классов, которые внутренне работают с неуправляемыми ресурсами. Например, может строиться класс, в котором присутствуют вызовы API-интерфейса Windows, основанного на С, с применением протокола обращения к платформе .NET Core, или какая-то низкоуровневая и сложная логика взаимодействия с СОМ. В табл. 9.2 приведено краткое описание некоторых наиболее интересных членов классаSystem.GC(полные сведения можно найти в документации по .NET Core).System.GCЧтобы проиллюстрировать использование типа
для получения разнообразных деталей, связанных со сборкой мусора, обновите операторы верхнего уровня в проектеSystem.GC:SimpleGCusing System;Console.WriteLine("***** Fun with System.GC *****");// Вывести оценочное количество байтов, выделенных в куче.Console.WriteLine("Estimated bytes on heap: {0}",GC.GetTotalMemory(false));// Значения MaxGeneration начинаются c 0, поэтому при выводе добавить 1.Console.WriteLine("This OS has {0} object generations.\n",(GC.MaxGeneration + 1));Car refToMyCar = new Car("Zippy", 100);Console.WriteLine(refToMyCar.ToString());// Вывести поколение объекта refToMyCar.Console.WriteLine("Generation of refToMyCar is: {0}",GC.GetGeneration(refToMyCar));Console.ReadLine();Вы должны получить примерно такой вывод:
***** Fun with System.GC *****Estimated bytes on heap: 75760This OS has 3 object generations.Zippy is going 100 MPHGeneration of refToMyCar is: 0Методы из табл. 9.2 более подробно обсуждаются в следующем разделе.
Принудительный запуск сборщика мусора
Не забывайте о том, что основное предназначение сборщика мусора связано с управлением памятью вместо программистов. Однако в ряде редких обстоятельств сборщик мусора полезно запускать принудительно, используя метод
. Взаимодействие с процессом сборки мусора требуется в двух ситуациях:GC.Collect()• приложение входит в блок кода, который не должен быть прерван вероятной сборкой мусора;
• приложение только что закончило размещение исключительно большого количества объектов, и вы хотите насколько возможно скоро освободить крупный объем выделенной памяти.
Если вы посчитаете, что принудительная проверка сборщиком мусора наличия недостижимых объектов может принести пользу, тогда можете явно инициировать процесс сборки мусора:
...// Принудительно запустить сборку мусора// и ожидать финализации каждого объекта.GC.Collect();GC.WaitForPendingFinalizers();...При запуске сборки мусора вручную всегда должен вызываться метод
. Благодаря такому подходу можно иметь уверенность в том, что все финализируемые объекты (описанные в следующем разделе) получат шанс выполнить любую необходимую очистку перед продолжением работы программы. "За кулисами" методGC.WaitForPendingFinalizers()приостановит вызывающий поток на время прохождения сборки мусора. Это очень хорошо, т.к. гарантирует невозможность обращения в коде к методам объекта, который в текущий момент уничтожается.GC.WaitForPendingFinalizers()Методу
можно также предоставить числовое значение, идентифицирующее самое старое поколение, для которого будет выполняться сборка мусора. Например, чтобы проинструктировать исполняющую среду о необходимости исследования только объектов поколения 0, можно написать такой код:GC.Collect()
