Используйте Claude Code для расследований производительности в повторяемом цикле: измерить, выдвинуть гипотезу, изменить минимально и переизмерить перед выпуском.

Ошибки производительности порождают догадки. Кто‑то замечает, что страница «кажется медленной» или API таймаутится, и быстрейшее решение — «прибрать» код, добавить кэш или переписать цикл. Проблема в том, что «кажется медленным» — не метрика, а «чище» — не значит быстрее.
Без измерений команды тратят часы на правку не той части. Горячий путь может быть в базе данных, в сети или в одной неожиданный аллокации, в то время как команда шлифует код, который почти не влияет на производительность. Хуже того, изменение, кажущееся разумным, может ухудшить ситуацию: лишний лог в tight‑цикле, кэш, увеличивающий давление на память, или параллельная работа, создающая конкуренцию за блокировки.
Догадки также рискуют повредить поведение. Меняя код ради скорости, вы можете изменить результаты, обработку ошибок, порядок выполнения или повторные попытки. Если вы не проверяете корректность и скорость вместе, можно «выиграть» бенчмарк и тихо выпустить баг.
Относитесь к работе над производительностью как к эксперименту, а не к спору. Цикл прост и повторяем:
Многие улучшения скромны: срезать 8% с p95, снизить пик памяти на 50 МБ или убрать один запрос к базе. Эти выигрыши важны, но только если они измерены, проверены и повторяемы.
Это работает лучше как цикл, а не как разовый запрос «сделать быстрее». Цикл держит вас честными, потому что каждое действие привязано к доказательству и числу, за которым можно следить.
Чёткая последовательность:
Каждый шаг защищает от разного вида самообмана. Измерение сначала останавливает «починку» того, что не было настоящей проблемой. Письменная гипотеза мешает менять пять вещей одновременно и гадать, что сработало. Минимальные изменения снижают риск поломать поведение или добавить новые узкие места. Переизмерение ловит плацебо‑победы (например, ускорение из‑за тёплого кэша) и выявляет регрессии.
«Готово» — это не чувство. Это результат: целевая метрика двинулась в нужную сторону, и изменение не привело к явным регрессиям (ошибки, рост памяти, ухудшение p95 или замедление соседних эндпоинтов).
Понимание, когда остановиться, — часть процесса. Остановитесь, когда выигрыши выровняются, метрика уже достаточна для пользователей, или когда следующая идея требует крупных рефакторов ради малого эффекта. Работа над производительностью всегда имеет альтернативную стоимость; цикл помогает тратить время там, где он окупается.
Если вы меряете пять вещей одновременно, вы не поймёте, что именно улучшилось. Выберите одну основную метрику для расследования и рассматривайте всё остальное как сигналы поддержки. Для пользовательских задач это часто latency. Для пакетной работы — throughput, время CPU, использование памяти или даже стоимость в облаке на запуск.
Будьте конкретны в сценарии. «API медленный» — слишком расплывчато. «POST /checkout с типичной корзиной из 3 товаров» — измеримо. Держите входы стабильными, чтобы числа имели смысл.
Запишите baseline и детали окружения до правки кода: размер датасета, тип машины, режим сборки, feature flags, конкуренция и прогрев. Этот baseline — ваш якорь. Без него любое изменение может выглядеть как прогресс.
Для latency опирайтесь на процентели, а не только на среднее. p50 показывает типичный опыт, а p95 и p99 — болезненный хвост, на который жалуются пользователи. Изменение, улучшающее p50, но ухудшающее p99, всё ещё может ощущаться медленнее.
Решите заранее, что считать «значимым», чтобы не праздновать шум:
Когда правила установлены, можно тестировать идеи, не двигая цель в процессе.
Начните с самого простого надёжного сигнала. Одна тайм‑метка вокруг запроса может показать, есть ли реальная проблема и насколько она велика. Глубокий профайлинг оставьте на тот момент, когда нужно объяснить, почему всё медленно.
Хорошие доказательства обычно приходят из смешения источников:
Используйте простые метрики, когда вопрос «медленнее ли и на сколько?». Профайлинг — когда вопрос «куда уходит время?». Если p95 удвоился после деплоя, начните с таймингов и логов, чтобы подтвердить регрессию и определить границы. Если тайминги показывают, что большая часть задержки внутри кода приложения (а не в БД), CPU‑профайлер или flame graph укажут конкретную функцию.
Держите измерения безопасными. Собирайте то, что нужно для отладки, а не пользовательский контент. Предпочитайте агрегаты (длительности, счётчики, размеры) вместо сырых payload и по умолчанию редактируйте идентификаторы.
Шум — реальность, поэтому делайте несколько замеров и отмечайте выбросы. Прогоните один и тот же запрос 10–30 раз и фиксируйте медиану и p95, а не один лучший прогон.
Запишите точный рецепт теста, чтобы можно было повторить после изменений: окружение, датасет, эндпоинт, размер тела запроса, уровень конкуренции и способ сбора результатов.
Начните с симптома, который можно назвать: «p95 вырос с 220 ms до 900 ms в пиковую нагрузку», «CPU держится на 95% на двух ядрах» или «память растёт на 200 МБ в час». Расплывчатые симптомы вроде «кажется медленным» ведут к случайным изменениям.
Затем переведите измеренное в область подозрения. Flame graph может показать большую долю времени в JSON‑сериализации, трейсы — медленный путь вызовов, а статистика БД — один запрос, доминирующий во времени. Выберите наименьшую область, которая объясняет большую часть стоимости: функцию, один SQL‑запрос или один внешний вызов.
Хорошая гипотеза — одно предложение, проверяема и связана с предсказанием. Вы просите проверить идею, а не инструмент творчески сделать всё быстрее.
Используйте формат:
Пример: "Because the profile shows 38% of CPU in SerializeResponse, allocating a new buffer per request is causing CPU spikes. If we reuse a buffer, p95 latency should drop by about 10-20% and CPU should fall by 15% under the same load." (пример оставлен на английском, чтобы сохранить имя функции и точность профиля).
Откройте альтернативы перед тем, как править код. Возможно, медленный участок — на самом деле внешняя зависимость, конкуренция за блокировки, изменение hit rate кэша или релиз, увеличивший размер payload.
Запишите 2–3 альтернативных объяснения, затем выберите то, которое лучше всего поддерживается доказательствами. Если изменения не сдвинули метрику, у вас уже будет следующая гипотеза.
Claude полезен в работе над производительностью, когда вы относитесь к нему как к аккуратному аналитику, а не к оракулу. Привязывайте каждое предложение к тому, что вы измерили, и убедитесь, что каждое утверждение можно опровергнуть.
Давайте ему реальные входные данные, а не расплывчатое описание. Вставьте небольшие, сфокусированные доказательства: сводку профиля, несколько строк лога вокруг медленного запроса, план запроса и конкретный путь в коде. Укажите числа «до» (p95, время CPU, время БД), чтобы он знал ваш baseline.
Попросите объяснить, что данные поддерживают, а что — нет. Затем форсируйте конкурирующие объяснения. Хороший промпт: «Дай 2–3 гипотезы и для каждой скажи, что её опровергнет.» Это мешает зациклиться на первой правдоподобной истории.
Перед правкой кода попросите наименьший эксперимент, проверяющий ведущую гипотезу. Делайте быстрые и обратимые проверки: один таймер вокруг функции, включить один флаг профилирования или выполнить EXPLAIN для запроса.
Если хотите строгую структуру вывода, запросите:
Если вывод не называет конкретную метрику, место и ожидаемый результат — вы снова гадали.
После того как появились доказательства и гипотеза, удержитесь от желания «почистить всё». Работу над производительностью легче доверять, когда изменение небольшое и его просто отменить.
Меняйте по одной вещи. Если вы подправили запрос, добавили кэш и отрефакторили цикл в одном коммите, вы не поймёте, что помогло (или навредило). Изменения в одной переменной делают следующее измерение значимым.
До правки кода запишите числовые ожидания. Пример: «p95 должен упасть с 420 ms до < 300 ms, и время БД должно упасть примерно на 100 ms.» Если результат не достигает цели, вы быстро поймёте, что гипотеза слабая или неполная.
Держите изменения обратимыми:
«Минимальный» не значит «тривиальный». Это значит сфокусированный: кэшировать один дорогой результат функции, убрать одну повторяющуюся аллокацию в tight‑цикле или не выполнять лишнюю работу для запросов, которым она не нужна.
Добавьте лёгкие тайминги вокруг подозреваемого узкого места, чтобы увидеть, что сдвинулось. Одна отметка времени до и после вызова (в логе или как метрика) может подтвердить, попали ли вы в узкое место или просто переместили время в другое место.
После изменения выполните точно тот же сценарий, что и для baseline: те же входы, окружение и форму нагрузки. Если тест зависит от кэшей или прогрева, укажите это явно (например: «первый запуск холодный, следующие 5 — тёплые»). Иначе вы «найдёте» улучшение, которое оказалось везением.
Сравнивайте результаты по тем же метрикам и процентилям. Средние могут скрывать боль — следите за p95 и p99, а также за throughput и CPU. Сделайте достаточно повторов, чтобы понять стабильность чисел.
Прежде чем радоваться, проверьте регрессии, которые не видны в заголовке:
Затем решайте на основе доказательств, а не надежд. Если улучшение реально и регрессий нет — оставляйте. Если результаты смешанные или шумные — откатывайте и придумывайте новую гипотезу либо ещё сильнее изолируйте изменение.
Если вы работаете на платформе, такой как Koder.ai, создание снапшота до эксперимента может сделать откат одним шагом, что упрощает тестирование смелых идей.
Наконец, запишите, что вы узнали: baseline, изменение, новые числа и вывод. Эта короткая запись поможет не повторять те же тупики в следующий раз.
Работа над производительностью обычно идёт по наклонной, когда связь между тем, что вы измеряли, и тем, что вы изменили, теряется. Держите чистую цепочку доказательств, чтобы уверенно сказать, что именно улучшило ситуацию или ухудшило.
Частые промахи:
Небольшой пример: эндпоинт кажется медленным, вы оптимизируете сериализатор, потому что он горячий в профиле. Затем тестируете с меньшим датасетом и всё кажется быстрее. В проде p99 ухудшается, потому что БД всё ещё узкое место, а изменение увеличило размер payload.
Если даёте Claude Code предложения по фиксам, держите его строго: просите 1–2 минимальных изменения, соответствующих уже собранным доказательствам, и требуйте плана переизмерения до принятия патча.
Обвинения в скорости разваливаются, когда тест нечёткий. Перед празднованием убедитесь, что можете объяснить, что измеряли, как измеряли и что изменили.
Начните с названия одной метрики и записи baseline. Включите детали, которые влияют на числа: тип машины, загрузка CPU, размер данных, режим сборки (debug vs release), feature flags, состояние кэша и конкуренция. Если вы не сможете воссоздать настройку завтра, у вас нет baseline.
Чек‑лист:
После того как числа улучшились, выполните быструю регрессионную проверку. Проверьте корректность (те же ответы), error rate и таймауты. Наблюдайте побочные эффекты вроде роста памяти, всплесков CPU, медленного старта или увеличения нагрузки на БД. Изменение, которое улучшает p95, но удваивает память, может быть плохой обмен.
Начните с одной цифры, которая соответствует жалобе — обычно это p95 latency для конкретного эндпоинта и входных данных. Запишите базовую метрику в тех же условиях (размер данных, конкуренция, холодный/тёплый кэш), затем измените одну вещь и измерьте снова.
Если вы не можете воспроизвести базовое значение, вы ещё не измеряете — вы предполагаете.
Хорошая базовая запись включает в себя:
Запишите это до того, как будете править код, чтобы не двигать цель.
Процентели лучше отражают пользовательский опыт, чем среднее. p50 показывает типичный случай, но жалобы приходят из медленного хвоста — это p95/p99.
Если p50 улучшился, а p99 ухудшился, система может казаться медленнее, хотя среднее выглядит лучше.
Используйте простые тайминги/логи, когда вопрос «медленнее ли и на сколько?». Профайлинг нужен, когда вопрос «куда уходит время?».
Практический поток: подтвердите регрессию таймингами запросов, затем профилируйте, только если замедление реально и локализовано.
Выберите одну основную метрику, остальные рассматривайте как страховочные сигналы. Частая связка:
Это предотвращает ситуацию, когда вы «выигрываете» одну диаграмму и при этом тихо создаёте тайм‑ауты или рост памяти.
Сформулируйте одно предложениe, привязанное к доказательству и предсказанию:
Если вы не можете назвать доказательство и ожидаемое изменение метрики, гипотеза не тестируемая.
Делайте изменения маленькими, сфокусированными и легко откатываемыми:
Маленькие диффы делают результаты измерений значимыми и снижают риск поломать поведение.
Перезапустите точно тот же сценарий, что и при baseline: те же входы, окружение и нагрузка. Если тест зависит от кэша или прогрева, явно оговорите это (например: «первый запуск холодный, следующие 5 — тёплые»). Иначе вы «найдёте» улучшение, которое оказалось случайностью.
Сравнивайте те же процентели и метрики. Средние могут скрывать проблему — смотрите p95 и p99, throughput и CPU. Сделайте достаточно повторов, чтобы понять, устаканились ли числа.
Перед празднованием проверьте регрессии, которые не видны в заголовках:
Дайте Claude реальные входные данные, а не расплывчатое описание. Вставьте небольшое, сфокусированное доказательство: сводку профиля, несколько строк лога вокруг медленного запроса, план запроса, и конкретный путь в коде. Укажите «до» числа (p95, CPU, время БД), чтобы было с чем сравнивать.
Попросите объяснить, что данные поддерживают, а что — нет. Заставьте генерировать конкурирующие объяснения. Полезный промпт: «Дай 2–3 гипотезы и для каждой скажи, что её опровергнет.» Это защищает от фиксации на первой правдоподобной истории.
Перед изменением запросите наименьший эксперимент для проверки гипотезы: один таймер вокруг функции, включить флаг профилирования или выполнить EXPLAIN для запроса.
Если вывод не называет конкретную метрику, место и ожидаемый результат — вы снова гадали.
Если улучшение реальное и регрессий нет — внедряйте. Если данные шумные или противоречивые — откатывайте и стройте новую гипотезу.