Как работает сборщик мусора (Garbage Collector) в Go? Опишите его основные принципы и фазы.

Ответ

Сборщик мусора (GC) в Go — это параллельный, трехцветный сборщик мусора с алгоритмом "mark-and-sweep" (пометь и собери), спроектированный для минимизации задержек (пауз "Stop The World").

Основные принципы:

  1. Параллельность: GC работает одновременно с выполнением основной программы (горутинами), используя доступные процессорные ядра, чтобы минимизировать время пауз.
  2. Трехцветный алгоритм: Объекты в памяти условно делятся на три цвета:
    • Белые: Кандидаты на удаление. Изначально все объекты белые.
    • Серые: Достижимые объекты, но их дочерние объекты еще не просканированы. Это "очередь на сканирование".
    • Черные: Достижимые объекты, все дочерние объекты которых также просканированы. Эти объекты точно не будут удалены в текущем цикле.
  3. Non-generational (Без поколений): В отличие от GC в Java или .NET, GC в Go не разделяет объекты на "молодые" и "старые" поколения. Это упрощает сам GC, но может приводить к большему объему работы на каждом цикле.

Фазы работы GC:

  1. Mark Setup (Настройка маркировки) - STW: Короткая пауза "Stop The World" (STW), во время которой включается барьер записи (write barrier). Барьер отслеживает все изменения указателей, чтобы GC не пропустил новые связи между объектами.
  2. Marking (Маркировка) - Конкурентно: Основная фаза. GC сканирует стеки горутин, глобальные переменные и помечает все достижимые объекты как серые. Затем он итеративно проходит по серым объектам, помечая их дочерние объекты и переводя родительский объект в черный цвет. Эта фаза выполняется параллельно с работой приложения.
  3. Mark Termination (Завершение маркировки) - STW: Вторая короткая пауза STW. GC завершает маркировку, обрабатывая оставшиеся объекты. После этой фазы все достижимые объекты — черные, а недостижимые — белые.
  4. Sweeping (Очистка) - Конкурентно: GC проходит по памяти и освобождает все белые (недостижимые) объекты. Эта фаза также выполняется параллельно.

Управление и тюнинг:

  • GOGC: Переменная окружения, которая контролирует, когда запускать следующий цикл GC. GOGC=100 (значение по умолчанию) означает, что GC запустится, когда объем новой выделенной памяти достигнет 100% от объема живой памяти после предыдущего цикла.
  • runtime.GC(): Позволяет принудительно запустить цикл сборки мусора.