Материал проходит вычитку — возможны неточности.
Урок 23 из 118

gctrace и снижение давления

На ночном инциденте Миша включил журнал сборщика и вместе с Аней читал строку за строкой: живое росло от цикла к циклу. Сергей охладил пыл: кэш тоже растёт, пока не выйдет на плато.

Главная мысль

GODEBUG=gctrace=1 печатает по строке на цикл GC — из неё видны давление на GC и подозрения на утечки; а главный способ «настроить» GC — убрать лишние аллокации.

Строка gctrace

gc 12 @0.183s 2%: 0.087+1.4+0.020 ms clock, 0.69+0/0.55/0.24+0.16 ms cpu, 58->59->29 MB, 60 MB goal, 8 P
  • 12 — номер цикла, @0.183s — момент от старта, 2% — доля времени в GC.
  • Три времени до ms clock — sweep termination, mark и mark termination: первое и третье — STW-паузы (0.087 и 0.020 мс), середина (1.4 мс) — конкурентная маркировка.
  • В ms cpu у mark-фазы тройная разбивка: assist / фон / простой.
  • 58->59->29 MB — куча в начале цикла, в конце и объём живых объектов.
  • 60 MB goal — целевой размер кучи от пейсера, 8 P — число процессоров.
  • Пример выше — формат не самых свежих версий: в свежих (Go 1.27+) между goal и числом P добавились поля MB stacks и MB globals.
  • Если строка заканчивается на (forced) — сборку вызвали вручную через runtime.GC.

Как читать на практике

Формат строки менялся между версиями, а читается одинаково: растущее от цикла к циклу третье число в ->->N MB — сигнал, а не доказательство утечки. Легитимный кэш тоже растёт, пока не выйдет на плато: проверяй стабилизацию и абсолютные значения (сравнение с лимитом), прежде чем объявлять утечку по паре циклов. Для точечных замеров есть runtime.ReadMemStats (вызов не бесплатен — на короткое время останавливает мир, не зови в горячем цикле) и runtime/metrics в свежих версиях — читается без остановки мира.

Как снизить давление

Сборщик настроен хорошо, и тюнинг GOGC — последний шаг, а не первый. Сначала убери лишние аллокации:

  • Возвращай значение вместо указателя там, где структура маленькая и копия дёшевая.
  • Не гоняй данные через any без необходимости: бокс значения крупнее машинного слова — аллокация.
  • Выделяй слайсы с реалистичной capacity, чтобы append не пересоздавал массивы.
  • Переиспользуй тяжёлые объекты через sync.Pool.
  • Строй строки через strings.Builder, а не конкатенацией в цикле.
В следующем уроке

Вы узнаете:

  • чем runtime/metrics лучше ReadMemStats
  • как отличить «живое растёт» от легитимного кэша
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Живое в gctrace растёт от цикла к циклу. Это утечка?

Вопрос 2 из 3

Что первым делом при давлении на GC?

Вопрос 3 из 3

Что означает (forced) в конце строки gctrace?

Итоги

gctrace — по строке на цикл: растущее «живое» — сигнал к проверке (стабилизация и абсолюты), а не доказательство утечки. Снижение давления — сначала аллокации, GOGC — потом.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки