Как работа garbage collector влияет на выполнение программы
Что проверяют
Понимаете ли вы, что сборщик в Go платит не длинными паузами, а процессорным временем и памятью, и умеете ли снижать нагрузку кодом, а не мифическими настройками.
Как отвечать
- В Go конкурентный трёхцветный mark and sweep с барьером записи, не перемещающий и не поколенческий. Объекты не переезжают, компактизации нет, поэтому возможна фрагментация, зато указатели стабильны.
- Пауз stop the world две, и обе короткие: старт цикла с включением барьера и завершение маркировки. Это обычно десятки или сотни микросекунд, и почти не зависит от размера кучи. Сама маркировка и очистка идут параллельно с программой.
- Цена в другом: маркировка съедает CPU (цель около 25% на сборку), а горутина, которая много аллоцирует, включается в assist и притормаживает именно там, где мусорит.
- Частоту задаёт
GOGC(по умолчанию 100: новый цикл, когда живая куча удвоится) иGOMEMLIMIT, мягкий лимит памяти из Go 1.19. СвязкаGOMEMLIMITс выключеннымGOGCчастый рецепт для контейнера с фиксированным лимитом и защита от OOM. - Как снизить давление: не давать объектам убегать в кучу (escape analysis,
go build -gcflags=-m), переиспользовать буферы черезsync.Pool, задавать capacity вmake, хранить значения вместо указателей, потому что сканируются именно указатели. - Диагностика:
GODEBUG=gctrace=1, pprof по heap и allocs, runtime/trace, метрики изruntime/metrics. Сначала измерение, потом оптимизация.
Где спотыкаются
Переносят опыт JVM и рассказывают про поколения, компактизацию и многосекундные паузы. В Go сборщик устроен иначе, и длинных пауз на большой куче он не даёт.
Считают, что runtime.GC() или debug.FreeOSMemory() в проде улучшают ситуацию. Обычно они только добавляют работы, память операционной системе рантайм возвращает сам.
Уверены, что горутина, которая ничего не выделяет, от сборщика не страдает. Барьер записи и assist затрагивают всю программу.
Ставят sync.Pool везде подряд. На мелких короткоживущих объектах он проигрывает обычной аллокации, а удержание в пуле больших буферов само по себе держит память.