Golang использует параллельный и сборщик мусора с низкой задержкой на основе марк-свип алгоритма.
Основные характеристики:
- Триколор-алгоритм (Three-color algorithm): Помечает объекты тремя цветами: белым (потенциальный мусор), серым (объект достижим, но его потомки не проинспектированы) и чёрным (объект и его потомки достижимы).
- Параллельность (Parallel): Работает параллельно с пользовательскими горутинами на нескольких ядрах, минимизируя время остановки.
- Конкурентность (Concurrent): Большая часть работы GC выполняется одновременно с выполнением программы.
- Минимизация стоп-ворлд времени (Low-latency Stop-The-World): Время остановки всех горутин (STW) крайне короткое, используется только для фазы "начало маркировки" (start of marking) и "завершение маркировки" (end of marking), чтобы обеспечить согласованность графа объектов.
- Переиспользуемые сканы (Stack scanning): Сканирование стеков также выполняется параллельно и конкурентно с STW.
- Целевой уровень заполнения хипа (Heap growth target): GC стремится поддерживать определённый процент заполнения хипа после каждого цикла, чтобы избегать слишком частых или слишком редких циклов. Этот порог можно контролировать через переменную
GOGC. По умолчанию GOGC=100, что означает, что GC запускается, когда размер хипа удваивается.
Цикл работы GC состоит из следующих фаз:
- GCstart: Короткая STW фаза. Определяются корневые объекты для маркировки.
- GCmark: Конкурентная фаза. GC обходит граф объектов, помечая достижимые объекты (серый цвет -> чёрный цвет). Использует write barrier для отслеживания изменений графа во время маркировки.
- GCmarktermination: Короткая STW фаза. Завершает маркировку и переключается с write barrier на sweep.
- GCsweep: Конкурентная фаза. Недостижимые (белые) объекты освобождаются. Эта фаза может происходить в фоновом режиме или по мере необходимости при выделении новой памяти.
GC в Go управляется автоматически и не требует ручного вызова в большинстве случаев. Производительность GC можно мониторить с помощью переменных среды GODEBUG=gctrace=1.
Пример мониторинга:
bash
Вывод gctrace показывает информацию о каждом цикле GC, включая время фаз, размер хипа и время STW.
Для оптимизации GC, помимо настройки GOGC, можно рассмотреть:
- Уменьшение количества аллокаций (например, переиспользуя буферы, избегая ненужных преобразований).
- Профилирование на предмет "escape analysis" для понимания, какие объекты аллоцируются на хипе.
- Использование пулов (
sync.Pool) для часто создаваемых и освобождаемых объектов.