Andriy Shyrokoryadov

.Net developer, data scientist

Что такое Garbage Collector - вопрос №14 на собеседование C# / .NET

Текст к видео "Что такое Garbage Collector" на канале YouTube

Во время обсуждения вопроса о значимых и ссылочных типах было указано, что наш код и данные могут храниться в двух местах в памяти: stack (стек, стопка) и heap (куча). Также было сказано, что стек управляет расположенными в нём данными самостоятельно. Однако очистка кучи от неиспользуемых объектов не происходит постоянно, а точнее сказать происходит иначе по сравнение со стеком.

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

  • Когда Garbage Collector начинает удалять неиспользуемые данные из кучи в памяти? - Garbage Collector начинает удаление объектов, когда на куче отсутствует место для создания нового объекта или операционная система сигнализирует отсутствие свободного места в памяти. Как правило очистка происходит тогда, когда приложении наименее нагружено.

  • Почему Garbage Collector начинает удалять неиспользуемые данные из кучи только в таких исключительных случаях? – Очистка памяти – это ресурсоемкий процесс, к тому же состояние объектов, которые остаются в памяти должно быть неизменно, поэтому работа всех потоков, связанных с приложением, приостанавливается. Из этого следует, что процесс очистки памяти не может запускаться слишком часто, так как это будет значительно влиять на производительность нашего приложения.

  • Как Garbage Collector знает, какие объекты должны быть удалены? – Объекты на куче, на которые отсутствуют ссылки в стеке являются объектами, которые будут удалены Garbage Collector’ом. Давайте еще раз разберем это предложение. Чтобы получить доступ к объекту в памяти из нашего кода у нас должна быть ссылка на объект, которая расположена на стеке. Если такое ссылки нет, то это значит, что мы не можем воспользоваться объектом на куче – у нас просто нет к нему доступа. Если у нас нет доступа к объекту, и мы не можем им воспользоваться, то такой объект на куче является бесполезным и будет удален сборщиком мусора.

  • Что конкретно делает Garbage Collector во время очистки памяти? – Сборщик мусора действует по принципу «помечай и собирай». Во время очистки он «помечает» используемые объекты и «собирает» их все вместе в определенном месте в памяти, делая размещение данных в памяти более компактным. Также после перемещения объектов в памяти восстанавливаются указатели на эти объекты.

  • Что происходит с объектами, которые «пережили» очистку Garbage Collector? – Изначально объекты приписываются к так называемой «генерации 0». Если объекты не были удалены во время очистки, то высока вероятность что данные объекты являются важными и будут существовать в приложении еще како-то время. Такие объекты приписываются к «генерации 1». Есть еще «генерация 2», в которую попадают все объекты, которые остались в памяти после двух и более очисток.

  • С какой целью объекты в памяти приписываются к определенным генерациям Garbage Collector’ом? – Как уже было сказано, очистка памяти – это ресурсоемкий процесс, и он занял бы значительное время при проверке всех объектов. Для минимизации времени работы Garbage Collector’а, при первой попытке очистки – проверяются объекты только «генерации 0». Если был освобожден достаточный объем памяти, то больше ничего не происходит, работа Garbage Collector’а прекращается. Однако если памяти всё еще недостаточно, начинается очистка объектов «генерации 1», и так далее до «генерации 2».

  • Можно ли программно вызвать очистку памяти Garbage Collector’ом? – Можно. Для этого используется статический метод System.GC.Collect(), однако, как правило, этот метод используется довольно редко. Примеры ситуаций когда необходимо явно вызвать очистку: 1. Перед началом исполнения кода, который не может (и не должен) быть прерван Garbage Collector’ом во время исполнения. 2. После создания большего количества объектов в приложении, необходимо очистить памяти и освободить некоторые ресурсы.