Оптимизация без измерения - это изменение кода с надеждой. Правильный цикл: метрика, гипотеза, базовый замер, профиль, изменение, повторная проверка.

метрика гипотеза базовый замер профиль одно изменение новый замер

Оптимизация - повторяемый эксперимент. Без базового и контрольного замера улучшение остается догадкой.

Сначала вопрос

Формулируем измеримую проблему:

  • p99 обработчика больше 300 мс при 500 RPS;
  • 150 аллокаций на запрос и частые GC;
  • 40 тысяч горутин после суток работы;
  • сервис не держит требуемые 1000 RPS.

У каждой проблемы свой профиль. Latency не всегда означает CPU, рост памяти не всегда утечка кучи, а медленная база не всегда плохой Go-код.

Базовый замер

Фиксируем версию, окружение, данные, нагрузку и прогрев. Сравнивать разные машины и случайные данные бессмысленно.

Минимальный набор:

  • p50/p95/p99 и долю ошибок;
  • RPS фактический, а не только заданный;
  • CPU, память, число горутин;
  • задержки зависимостей;
  • время теста и состояние кэшей.

Базовый результат сохраняется до изменения. Иначе «стало быстрее» доказать нечем.

Гипотеза

Хорошая гипотеза объясняет причину и предсказывает эффект: «сборка строки через fmt.Sprintf создаёт большую часть аллокаций, замена на strings.Builder снизит их вдвое и уменьшит долю GC в CPU».

После гипотезы выбираем профиль: heap для аллокаций, CPU для процессора, goroutine для ожидания, trace для планировщика, метрики зависимости для сети и базы.

Одно изменение за раз

Меняем одну причину, повторяем тот же сценарий. Если одновременно поменять SQL, сериализацию и пул, невозможно понять вклад каждой.

Результат сравниваем по абсолютным значениям и статистической устойчивости. Один быстрый прогон ничего не доказывает: нужны повторы и сравнение распределения.

Коротко

  • Сначала измеримая проблема, затем код.
  • Базовый замер включает окружение и нагрузку.
  • Гипотеза предсказывает и причину, и эффект.
  • Одно изменение за раз, повторные проверки обязательны.