Производительность
GC: укроти death-spiral
Читать про death-spiral — не то же самое, что вытащить сервис из него. Построй небольшой аллокационно-тяжёлый сервер, загони его в GC-беду и применяй лестницу фиксов юнита, пока числа не вернутся — с доказательством на каждом шаге.
Преврати ментальную модель юнита в воспроизводимый инженерный цикл: заинструментируй аллокации и GC, диагностируй горячую точку по профилю, сократи аллокации, защити границу памяти и подтверди фикс метриками до/после.
Возьми намеренно аллокационно-тяжёлый HTTP-сервис (свой или стартовый ниже) и снизь его долю GC CPU ниже 5%, а p99 — до целевого, не меняя коллектор, доказывая каждый шаг измерениями.
- Таблица до/после: allocation rate, GC CPU %, p99 пауза и p99 задержка запроса — измеренные под одинаковой нагрузкой, а не оценённые.
- Профиль аллокаций чётко показывает уменьшение топовых точек после фикса (перепрофилировано, а не предположено).
- Доля GC CPU держится ниже ~5%, и сигнатура death-spiral исчезла из gctrace при устойчивой нагрузке.
- Абзац-разбор: какой рычаг применён для каждой горячей точки и почему он встал выше тюнинга коллектора.
- Добавь одностраничный on-call runbook: быстрый triage по четырём панелям, типичные причины аллокаций для твоего рантайма, лестница приоритетов фиксов и чек-лист верификации.
- Добавь защиту от allocation-DoS — лимит размера тела запроса и потолок размера результата — и покажи, что сервис остаётся ограниченным под флудом негабаритных payload'ов.
- Добавь CI-гейт, который нагружает canary, диффит профиль аллокаций против main и валит сборку, если доля аллокаций любой функции выросла больше чем на 20%.
- Повтори эксперимент на втором рантайме (например, добавь версию на JVM или Node) и сравни, как один и тот же паттерн аллокаций проявляется под другим коллектором.
Это цикл, который ты будешь запускать в каждом реальном GC-инциденте: сначала инструментируй, диагностируй по профилю, чини с верха лестницы (устранить раньше, чем пулить, раньше, чем тюнить, раньше, чем менять), защити границу памяти через GOMEMLIMIT и подтверди числами до/после под идентичной нагрузкой. Сделав это раз на игрушечном сервисе, ты доводишь production-версию до уровня мышечной памяти.