Перейти к содержанию

Бенчмарки

Что здесь измеряется

Только накладные расходы фреймворка: роутинг, разбор запроса, сборка ответа. Бенчмарк вызывает ASGI-приложение каждого фреймворка напрямую, в одном процессе — без сети и без веб-сервера. О сквозной HTTP-пропускной способности он не говорит ничего: там у обоих фреймворков одинаково доминируют uvicorn и база данных.

Как замерялось

  • Два одинаковых endpoint'а в каждом фреймворке: статический GET /v1/ping и динамический GET /v1/item/{id}.
  • 1 000 вызовов на прогрев, затем 50 000 замеряемых. В таблице — медиана трёх прогонов.
  • Логирование запросов выключено в обоих приложениях, чтобы в замер не попадал вывод в консоль.
  • Перед замером проверено, что оба приложения возвращают одинаковые ответы 200.

Результаты

Python 3.14.3, Windows 11, AMD Ryzen, FastAPI 0.139. Абсолютные числа зависят от машины — важны соотношения.

Маршрут EndoCore FastAPI Соотношение
Статика GET /v1/ping 23 800 req/s (42 µs) 11 000 req/s (91 µs) 2.2×
Динамика GET /v1/item/{id} 30 800 req/s (32 µs) 8 600 req/s (116 µs) 3.6×

Откуда разрыв

EndoCore резолвит маршрут одним проходом по trie, построенному при старте, а обычный handler(request) вообще пропускает разрешение зависимостей. FastAPI гоняет свою машинерию валидации и сериализации даже там, где она не нужна — эта работа покупает фичи, но на тривиальном endpoint'е это чистые накладные расходы. Голый Starlette оказался бы куда ближе к EndoCore.

Важен ли этот разрыв на практике? Редко. Диспатч стоит 30–120 µs; один индексированный запрос к базе стоит дороже. Выбирайте фреймворк по удобству, а не по этой таблице.

Воспроизвести

pip install endocore fastapi
python benchmarks/bench.py 50000

Скрипт (benchmarks/bench.py) собирает оба приложения, прогревает их и печатает req/s и соотношение для каждого маршрута.

Что не измеряется

  • HTTP-транспорт — это uvicorn, одинаковый у обоих.
  • Сериализация больших JSON — оба endpoint'а возвращают крошечные тела.
  • Латентность базы — обычное настоящее узкое место; асинхронная ORM держит event loop свободным, пока идут запросы.