Оптимизация кода с ИИ: сначала измерения

Как оптимизировать производительность кода с ИИ-агентами: профилируйте, давайте агенту реальные профили, чините N+1 и раздутый бандл, доказывайте выигрыш бенчмарком.

Solviera Teknoloji 8 мин чтения

Чтобы оптимизировать производительность кода с помощью ИИ, измеряйте до того, как писать промпт: профилируйте медленный путь, отдайте агенту профиль, попросите минимальное изменение, которое убирает горячую точку, и принимайте его, только когда бенчмарк показывает разницу. Агенты для программирования вроде Claude Code, Codex и Gemini CLI быстро читают flame graph, прослеживают горячую функцию до её вызывающих и переписывают запросы. Без данных они делают то же, что и любой человек: гадают. А угаданные оптимизации — самые дорогие, потому что код становится труднее читать, но не быстрее.

В этом руководстве — процесс, который выдерживает практику: определить цель, профилировать, передать доказательства, менять по одному, проверять бенчмарком и закреплять выигрыш защитой от регрессий. Попутно разобраны проблемы, из-за которых тормозит большинство реальных приложений: N+1 запросы, размер бандла и отсутствие кеша.

Начинайте с числа, а не с ощущения

«Дашборд тормозит» — это не задача. Превратите это в то, что агент может проверить:

  • Что медленно: один эндпоинт, одна загрузка страницы, одна CLI-команда, одна пакетная задача.
  • Насколько медленно сейчас, по измерениям: p95-задержка эндпоинта, time to interactive страницы, время работы скрипта.
  • Что значит «достаточно быстро»: цель, например «меньше 300 мс на p95» или «импорт 100 тыс. строк завершается быстрее минуты».
  • При каких условиях: объём данных, холодный или прогретый кеш, продакшен-сборка или dev-сервер.

Последний пункт отсекает много лишней работы. React-приложение на dev-сервере, Node-сервис без NODE_ENV=production или Python-задача на десяти строках тестовых данных покажут горячие точки, которых в продакшене нет. Измеряйте то, что выпускаете.

Шаг 1: профилируйте медленный путь

Выберите профилировщик под то место, где уходит время.

В браузере

Панель Performance в Chrome DevTools записывает трассировку: длинные задачи, выполнение скриптов, layout, сетевой водопад. Lighthouse даёт лабораторную оценку с конкретными возможностями для улучшения. Lighthouse CLI удобен тем, что пишет файл, который можно отдать агенту:

npm install -g lighthouse
lighthouse https://localhost:3000/dashboard \
  --only-categories=performance \
  --output=json --output-path=./lighthouse.json

Если ваш агент поддерживает MCP, MCP-сервер Chrome DevTools позволяет ему самому запустить трассировку производительности и прочитать выводы:

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["-y", "chrome-devtools-mcp@latest"]
    }
  }
}

В Node.js

В Node есть встроенный сэмплирующий профилировщик. --cpu-prof при завершении процесса пишет файл .cpuprofile, который можно открыть в панели Performance в DevTools или отдать агенту:

node --cpu-prof --cpu-prof-dir=./profiles server.js
# run the slow request a few times, then stop the server

Более старый флаг --prof пишет лог V8, который node --prof-process превращает в текстовый отчёт, — агенту его читать очень легко:

NODE_ENV=production node --prof server.js
node --prof-process isolate-0x*-v8.log > processed.txt

Для проблем с памятью --heap-prof точно так же пишет .heapprofile.

В Python

py-spy сэмплирует запущенный процесс без изменений в вашем коде, поэтому это безопасный выбор для работающего сервиса:

py-spy top --pid 12345                    # live view, like top
py-spy record -o profile.svg --pid 12345  # flame graph
py-spy record -o profile.svg -- python import_job.py

Для скрипта, который вы запускаете сами, cProfile из стандартной библиотеки даёт точное число вызовов:

python -m cProfile -s cumtime import_job.py | head -40

По состоянию на октябрь 2026 года в Python 3.15 также есть пакет profiling со статистическим профилировщиком (python -m profiling.sampling), а cProfile остаётся псевдонимом его трассирующего профилировщика; в более ранних версиях используйте cProfile и py-spy.

В базе данных

Про время запросов база данных уже знает ответ: лог медленных запросов, pg_stat_statements в PostgreSQL и EXPLAIN ANALYZE для отдельного запроса. Как читать планы запросов и выбирать индексы с агентом, рассказано в статье пишем SQL с ИИ, так что здесь мы это не повторяем.

Шаг 2: отдайте агенту доказательства

Теперь у агента есть с чем работать. Передайте профиль и контекст и попросите анализ до кода:

Эндпоинт /api/orders в продакшене отвечает примерно за 1,8 с на p95;
цель — 300 мс. Во вложении: processed.txt из node --prof-process для
50 запросов и лог медленных запросов за тот же период.
Пока не меняй код. Перечисли три главные горячие точки с доказательствами
из профиля для каждой (функция, собственное или общее время, число
вызовов), вероятную причину в нашем коде (файл и строка) и предлагаемое
исправление. Упорядочь их по ожидаемому эффекту.

Несколько привычек, с которыми этот шаг работает:

  • Давайте сырой вывод, а не свой пересказ. В вашем пересказе уже сидит ваша догадка.
  • Требуйте доказательство для каждого утверждения. «Эта функция медленная» должно сопровождаться цифрой из профиля.
  • Держите агента на горячем пути. Код, который занимает 2% времени, не стоит переписывать, каким бы уродливым он ни был.

Если агент говорит что-то вроде «по профилю узкое место видно неясно», поверьте ему и снимите профиль получше — под большей нагрузкой или на продакшен-сборке. Это гораздо лучший результат, чем уверенная догадка.

Шаг 3: напишите бенчмарк до исправления

Бенчмарк — это ваш шаг проверки. Напишите его, запустите на текущем коде и сохраните базовую линию до любых изменений.

Для команды или скрипта hyperfine запускает её много раз и сообщает среднее и разброс:

hyperfine --warmup 3 'node scripts/build-report.js'

Для функции используйте поддержку бенчмарков в своём стеке: go test -bench=. -benchmem в Go, pytest-benchmark в Python, бенчмарки в вашем тестовом раннере для JavaScript. Для эндпоинта — короткий нагрузочный тест с фиксированным числом запросов к продакшен-сборке.

Затем сообщите агенту правило:

Вот бенчмарк и его базовый результат. Вноси по одному изменению за раз.
После каждого изменения запускай тесты и бенчмарк трижды и сообщай
результат до/после. Если изменение не улучшает результат сверх шума,
откати его и скажи мне, даже если считаешь, что оно должно помогать.

Важны две детали. Сравнивайте на одной машине с одними данными, потому что ноутбуки троттлят, а кеши прогреваются. И запускайте тесты вместе с бенчмарком: более быстрая функция, которая возвращает неправильный ответ, — это баг. Если у оптимизируемого кода нет тестов, сначала добавьте их; как получить от агента полезные тесты, показано в статье пишем unit-тесты с ИИ.

Куда обычно уходит время

В реальных приложениях большую часть замедлений дают несколько типичных проблем. Их и проверяйте первыми.

N+1 запросы

Классика: загрузить список, а затем внутри цикла или шаблона выполнять по одному дополнительному запросу на каждый элемент. С десятью строками в разработке выглядит нормально, а с двумя тысячами в продакшене падает. Исправление — загружать связанные данные одним-двумя запросами с помощью средства, которое даёт ваша ORM:

СтекЖадная загрузка
Djangoselect_related (join), prefetch_related (отдельный запрос)
Railsincludes, а гем Bullet находит N+1 в разработке
SQLAlchemyselectinload, joinedload
Prismainclude

Агенты хорошо делают это исправление, когда знают, где проблема. Включите логирование запросов, один раз откройте медленную страницу и отдайте агенту лог: повторяющийся шаблон запроса с разными ID — это отпечаток пальца. Затем попросите исправление и тест, который проверяет число запросов на этой странице, чтобы проблема не вернулась незаметно.

Размер бандла

Во фронтенде самый большой рычаг — часто сам JavaScript, который вы отдаёте. Сначала измерьте, что лежит в бандле, с помощью source-map-explorer или webpack-bundle-analyzer (или анализатора для вашего сборщика), а затем ищите типичные причины:

  • большая библиотека импортирована ради одной функции,
  • целый набор иконок или локалей подтянут одним импортом,
  • тяжёлые компоненты грузятся при первой отрисовке, хотя могли бы грузиться лениво,
  • одна и та же зависимость попала в бандл дважды в разных версиях.

Отдайте агенту вывод анализатора и попросите изменения, отсортированные по сэкономленным байтам. Затем сравните результат сборки до и после — так же, как сравниваете бенчмарк.

Повторная работа и кеширование

Кеш — правильный ответ, когда один и тот же дорогой результат снова и снова вычисляется с одними и теми же входными данными. И неправильный, когда вычисление можно просто удешевить или когда никто не решил, что происходит при изменении данных. Прежде чем принять кеш от агента, спросите его:

Для этого кеша: какой ключ, что его инвалидирует, какое максимальное
устаревание мы допускаем, сколько памяти он может занимать и что
происходит при холодном старте? Покажи измеренный hit rate или профиль,
который его оправдывает.

Если ответы расплывчатые, кеш потом превратится в баг-репорт. Часто лучшее исправление находится раньше в цепочке: недостающий индекс, запрос, который тянет все столбцы, цикл, который на каждой итерации заново вычисляет одно и то же значение.

Алгоритмические проблемы

Иногда профиль показывает одну функцию с огромным числом вызовов: вложенный цикл по двум спискам, .find() внутри .map(), сортировку внутри цикла. Замена линейного поиска на Map или Set — классическое исправление для агента, и бенчмарк сразу скажет, было ли оно важно.

Избегайте преждевременной и спекулятивной оптимизации

Агенты любят оптимизировать. Попросите «улучшить производительность» файла, и агент мемоизирует компоненты, перепишет циклы и везде добавит кеши. Большинство таких изменений ничего измеримо не сдвигают, а код становится труднее менять. Правила, которые стоит прямо прописать в инструкциях проекта:

## Работа над производительностью
- Никакой оптимизации без профиля или бенчмарка, который показывает проблему.
- Одно изменение на коммит, с цифрами до/после в сообщении.
- Вне измеренных горячих путей читаемость важнее микрооптимизаций.
- Не добавляй кеши, воркеры или новые зависимости, не спросив.

То же относится к собственным предложениям агента во время несвязанной работы. Если он сообщает «заодно я ещё оптимизировал…», попросите цифры или попросите откатить. Если после оптимизации что-то всё же сломалось, как сузить поиск без догадок, рассказано в статье отладка кода с ИИ.

Шаг 4: защитите выигрыш

Производительность ухудшается тихо, по одному разумному изменению за раз. Превратите каждое исправление в проверку, которая громко падает:

  • Тесты на число запросов. Проверяйте, что страница заказов выполняет не больше фиксированного числа запросов. В большинстве фреймворков для этого есть хелпер, например assertNumQueries в Django.
  • Бюджеты бандла. Инструменты вроде size-limit роняют сборку, когда бандл вырастает сверх заданного размера.
  • Lighthouse в CI. Запускайте Lighthouse CLI на превью-сборке и роняйте проверку ниже порога оценки на важных страницах.
  • Бенчмарки против базовой линии. Сохраните базовую линию и сравнивайте; в Go benchstat сравнивает два прогона бенчмарков и говорит, значима ли разница.

Агенты хорошо пишут такие защиты, и стоит просить их в той же задаче, что и исправление: «исправь N+1 и добавь тест, который поймал бы его».

Как это делать в AgentVera

AgentVera — десктопное приложение, которое запускает CLI агентов для программирования, такие как Claude Code, Codex и Gemini CLI, рядом друг с другом. Несколько его функций подходят под этот цикл:

  • Браузер, которым управляет агент. Браузер агента — это отдельный профиль Chrome, которым агенты пользуются через Playwright MCP, со встроенными DevTools и консолью, так что агент может сам открыть медленную страницу, а вы — наблюдать.
  • Доказательства одним сочетанием клавиш. Отправка агенту (⌘⇧L) отправляет агенту вывод терминала, выделение в редакторе, diff или консоль браузера. Вывод профилировщика в терминале уходит агенту без копирования; очень длинный вывод обрезается на 12 000 символов, поэтому отправляйте верх отчёта или сохраните его в файл.
  • Планы запросов рядом с кодом. Менеджер баз данных (Pro) открывает PostgreSQL, MySQL и SQLite с SQL-редактором, который показывает планы EXPLAIN, а агенты могут обращаться к базе через его встроенный инструмент.
  • Бенчмарки как критерии приёмки. Напишите в сообщении «тесты проходят, а бенчмарк минимум на 30% быстрее базовой линии», и Verify проверит это в конце хода с помощью проверяющего, который запускает команды, но не может править файлы.
  • Откат неокупившейся оптимизации. Чекпоинты сохраняют снимок каждого хода, так что откат эксперимента — один клик.
  • Два подхода одновременно. В сетке рабочего пространства запустите двух агентов в отдельных worktree — скажем, одного на кеширование, другого на запрос — и оставьте того, у кого цифры лучше.

Итоги

Оптимизация производительности кода с помощью ИИ — та же дисциплина, что и без него, только быстрее: ясная цель, профиль, переданные агенту доказательства, по одному изменению за раз, бенчмарк как доказательство и защита, которая удерживает выигрыш. Агент читает и переписывает, а решают цифры. Если замедление пришло вместе с обновлением зависимостей, процесс из статьи обновление зависимостей с ИИ поможет выяснить, какой пакет виноват.

Чтобы попробовать этот процесс на своём проекте, скачайте AgentVera.

Вопросы

Может ли ИИ-агент найти проблемы с производительностью, просто читая код?

Он может указать вероятных подозреваемых, например запрос внутри цикла, но не может знать, какой из них важен при ваших данных и нагрузке. Дайте ему профиль, лог медленных запросов или трассировку, и он сосредоточится на коде, который действительно отнимает время.

Какой профилировщик выбрать?

Для браузера — панель Performance в Chrome DevTools и Lighthouse. Для Node.js — node --cpu-prof, который пишет файл .cpuprofile, открываемый в DevTools. Для Python — py-spy для запущенных процессов и cProfile для скрипта, который вы можете запустить сами.

Как понять, что оптимизация сработала?

Измерьте одно и то же до и после, по нескольку запусков, на одной машине. Инструмент для бенчмарков вроде hyperfine для команд или поддержка бенчмарков в вашем тестовом фреймворке сделает повторные запуски за вас. Если разница в пределах шума, оптимизация не сработала.

Почему агенты предлагают оптимизации, которые не помогают?

Без измерений модель скатывается к общим советам: мемоизировать это, взять цикл побыстрее, добавить кеш. Такие изменения добавляют сложности и часто ничего не меняют. Требуйте доказательство для каждого предложения и отклоняйте всё, что не связано с измеренной горячей точкой.

Как не дать производительности снова ухудшиться?

Превратите каждое исправление в проверку: тест, который ограничивает число запросов на странице, бюджет размера бандла в CI или бенчмарк, сравниваемый с базовой линией. Проверка упадёт раньше, чем регрессия дойдёт до пользователей.

Соберите своих агентов за одним столом.

Скачайте AgentVera бесплатно; ваши установленные CLI уже готовы к работе.

Другие статьи