Я пишу этот пост как последнюю часть серии Управление памятью в C # (« Часть 1 и Часть 2 )». В этом сообщении объясняется, что делает Сборщик мусора и как он работает в среде .NET. (Большая часть представленной здесь информации цитируется из документации Microsoft)
Во-первых, давайте начнем с Common Language Runtime.
Общеязыковая среда выполнения
.NET Framework предоставляет среду выполнения, называемую Common Language Runtime (CLR),, которая запускает код и предоставляет службы, упрощающие процесс разработки.
На следующем рисунке показана связь среды CLR и библиотеки классов с вашими приложениями и системой в целом.
Компоненты CLR:
В среде CLR сборщик мусора служит автоматическим диспетчером памяти. C # и другие языки поверх CLR собираются сборщиком мусора.
Сборщик мусора
Сборщик мусора (GC) .NET управляет выделением и освобождением памяти для вашего приложения.
GC дает следующие преимущества:
- Позволяет разрабатывать приложение, не освобождая память.
- Эффективно распределяет объекты в управляемой куче.
- Восстанавливает объекты, которые больше не используются, очищает их память и сохраняет доступную память для будущих распределений.
- Обеспечивает безопасность памяти, гарантируя, что объект не может использовать содержимое другого объекта.
Все процессы на одном компьютере используют одну и ту же физическую память. У каждого процесса есть свое собственное отдельное виртуальное адресное пространство. Как разработчик приложений вы работаете только с виртуальным адресным пространством и никогда не манипулируете физической памятью напрямую. GC выделяет и освобождает виртуальную память в управляемой куче.
Кучу можно рассматривать как скопление двух куч: кучи больших объектов и кучи малых объектов. Куча больших объектов содержит очень большие объекты размером 85 000 байт и более (Объекты в куче больших объектов обычно представляют собой массивы).
Сборка мусора запускается, когда выполняется одно из следующих условий:
- В системе мало физической памяти.
- Объем памяти, используемый выделенными объектами в управляемой куче, превышает допустимый порог.
- Вызывается метод GC.Collect. (Почти во всех случаях вам не нужно вызывать этот метод, потому что сборщик мусора работает непрерывно. Этот метод в основном используется для уникальных ситуаций и тестирования.)
Перед запуском сборки мусора все управляемые потоки приостанавливаются, за исключением потока, который запустил сборку мусора.
Поколения
В 1984 году Дэвид Ангар выдвинул гипотезу поколений, которая породила поколений сборщиков мусора:
Молодые объекты умирают молодыми. Поэтому алгоритм рекультивации не должен тратить время на старые объекты.
Копирование выживших дешевле сканирования трупов.
Куча организована по поколениям, поэтому она может обрабатывать долгоживущие и недолговечные объекты. В куче есть три поколения объектов:
Поколение 0: это самое молодое поколение, содержащее недолговечные объекты. Примером недолговечного объекта является временная переменная. Сборка мусора чаще всего происходит в этом поколении.
Недавно размещенные объекты образуют новое поколение объектов и неявно являются коллекциями Gen 0, если только они не являются большими объектами, и в этом случае они помещаются в кучу больших объектов в Коллекция Gen 2.
Большинство объектов отправляются на сборку мусора в Gen 0 и не доживают до следующего поколения. Объекты, оставшиеся после сборки мусора Gen 0, переводятся в Gen 1.
Поколение 1: это поколение содержит недолговечные объекты и действует как буфер между короткоживущими объектами и долгоживущие объекты. Объекты, оставшиеся после сборки мусора Gen 1, переводятся в Gen 2.
Поколение 2. Это поколение содержит долгоживущие объекты. Примером объекта-долгожителя является объект в серверном приложении, который содержит статические данные, живущие на протяжении всего процесса. Объекты, прошедшие сборку мусора Gen 2, остаются в Gen 2.
Собирать поколение означает собирать предметы в этом поколении и во всех его младших поколениях. Сборка мусора Gen 2 также известна как полная сборка мусора, поскольку она освобождает все объекты во всех поколениях.
Как работает сборщик мусора
Сборка мусора состоит из следующих этапов:
Маркировка. Находит и создает список всех живых объектов.
Перемещение: обновляет ссылки на объекты, которые будут уплотнены.
Уплотнение: освобождает пространство, занимаемое мертвыми объектами, и уплотняет уцелевшие объекты. На этапе уплотнения объекты, пережившие сборку мусора, перемещаются к более старому концу сегмента. (Обычно куча больших объектов не сжимается, поскольку копирование больших объектов снижает производительность.)
GC использует следующую информацию, чтобы определить, живы ли объекты:
- Корни стека: переменные стека, предоставляемые JIT-компилятором и обходчиком стека.
- Дескрипторы сборки мусора: дескрипторы, которые указывают на управляемые объекты и могут быть выделены пользовательским кодом или средой CLR.
- Статические данные: статические объекты в доменах приложений, которые могут ссылаться на другие объекты.
Кроме того, существуют неуправляемые ресурсы, такие как файловые потоки, подключения к сети / базе данных, о которых вам нужно позаботиться. В этом случае вам нужно использовать Finalizer & Dispose. Вы можете обратиться к этому посту для получения дополнительной информации.
Наконец, я рекомендую вам посмотреть видео ниже, которое наглядно объясняет тему с очень полезной демонстрацией в конце.
Надеюсь, вы нашли этот пост полезным и легким для понимания. Как я уже упоминал в начале, это последняя часть серии Управление памятью C #. Если вам интересно, вы можете прочитать и другие сообщения (Часть 1 и Часть 2).
КОНЕЦ :)
Ссылки
https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/
https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
https://chodounsky.net/2017/05/03/garbage-collection-in-c-sharp/