Как оптимизировать производительность (профилирование async кода)?
Подробный ответ
Сначала измерения
Нельзя оптимизировать FastAPI только по ощущениям. Нужно определить SLI и SLO, собирать p50, p95 и p99 latency, RPS, error rate, CPU, память, число соединений с базой, event loop lag и время внешних зависимостей.
Где искать узкие места
медленные SQL-запросы, отсутствие индексов и N+1;
блокирующий синхронный код внутри
async def;долгие HTTP-вызовы без корректных тайм-аутов и connection pooling;
слишком большие JSON-ответы и дорогая сериализация;
неверный размер database pool или слишком много workers;
CPU-bound вычисления в web-процессе.
Профилирование async-кода
Для production используют distributed tracing, например OpenTelemetry, и APM, чтобы видеть путь запроса через API, базу и внешние сервисы. Для локального анализа применяют профилировщики Python, такие как py-spy или scalene, а также логи медленных SQL и EXPLAIN ANALYZE в PostgreSQL.
Блокирующие вызовы
Синхронный запрос к сети, файловой системе или синхронной базе внутри async def блокирует event loop. Нужно заменить его асинхронной библиотекой, выполнить в threadpool через asyncio.to_thread() или изменить endpoint на обычный def, если весь используемый стек синхронный.
import asyncio
@app.get('/report')
async def build_report():
report = await asyncio.to_thread(build_cpu_or_blocking_report)
return reportБаза и внешние запросы
Для базы нужно профилировать запросы, добавлять индексы по фактическим фильтрам, устранять N+1 и использовать connection pool. Для внешних HTTP-вызовов нужен один переиспользуемый async client, connect/read timeout, ограничения на retries и circuit breaker для нестабильных зависимостей.
Нагрузочное тестирование
После изменения проводят воспроизводимый нагрузочный тест с реалистичным распределением endpoints, payload и конкурентности. Сравнивают метрики до и после, следят за saturation базы и проверяют, что оптимизация не ухудшила корректность или отказоустойчивость.
Как ответить на собеседовании
Я начинаю с метрик и tracing, чтобы найти конкретный узкий участок: SQL, внешний сервис, блокировку event loop или сериализацию. В async FastAPI отдельно проверяю, нет ли синхронного блокирующего кода внутри async def. Затем оптимизирую целевой участок, например запросы и пулы БД, и подтверждаю результат повторным нагрузочным тестом по p95/p99 и throughput.
Оцени свой прогресс