Performance and Benchmarks¶
Results¶
Sync¶
Why so fast?
We utilize
msgspec.json.decode()andmsgspec.json.encode()to parse json, it is the fastest json parsing tool in Python landWe can support
msgspec.Structmodels, which are faster than pydanticWe provide
django.urls.path()drop-in Routing replacement which is x51 times as fast as the default oneWe validate data smartly: we prepare models for validation in advance, so no runtime magic ever happens
We have special “production mode” with fewer checks, so we can have the best of two worlds: strict development workflow and fast runtime for real users
Async¶
While fastapi is faster at the moment, we have several ideas
to optimize django-modern-rest even further,
so it can be on par (or even faster!)
with the fastest python web frameworks in existence.
While keeping 100% of compatibility with the older libs and tools.
Technical details¶
See source code for our benchmark suite.
Benchmarks!¶
Important Notice¶
All benchmarks are always synthetic. Benchmarks do not test real performance, they test ideas of performance.
Environment¶
Python:
3.13.7, no JIT, no free-threadingOS: MacOS 15.6.1
Device: Apple M2 Pro, mid 2023, 16 Gb of RAM
Assumptions¶
We test only the API part, because
django-modern-restdoes not include any database features, we want to make sure that the part that we are covering is measured, not something elseWe test the minimal possible app
We use the same exact data for all apps
We test production-like setups with
DEBUG=FalseWe test both sync (
gunicorn) and async (uvicorn) version if the requested mode is supported (yes, DRF, we are looking at you)But, we don’t compare sync to async and vice versa, because they have different logic, different deploy strategies, etc
Results¶
Async¶
framework |
is_async |
rps |
tpr |
|---|---|---|---|
fastapi |
True |
10854.6 |
1.843 |
dmr |
True |
7026.27 |
2.846 |
ninja |
True |
4359.12 |
4.588 |
Sync¶
framework |
is_async |
rps |
tpr |
|---|---|---|---|
dmr |
False |
5774.94 |
3.463 |
ninja |
False |
3888.13 |
5.144 |
drf |
False |
3024.24 |
6.613 |
Running the script:¶
Pre-requirements:
Run from benchmarks/ directory:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
make bench
Manual debug¶
Single request:
curl -X POST \
'http://127.0.0.1:8000/async/user/?per_page=1&count=2&page=3&filter=abc' \
-d @payload.json \
-H 'Content-Type: application/json' \
-H 'X-API-Token: some-token-example' \
-H 'X-Request-Origin: some-origin'
Manual bench:
ab -c 20 -n 1000 -l -p payload.json \
-H 'X-API-Token: some-token-example' \
-H 'X-Request-Origin: some-origin' \
-T 'application/json' \
'http://127.0.0.1:8000/async/user/?per_page=1&count=2&page=3&filter=abc'
Feature benchmarks¶
We also benchmark several our features that can be used independently.
Pre-requirements:
path replacement¶
See our routing guide
make -C benchmarks bench-resolver produces:
Summary
dmr-best ran
1.09 ± 0.01 times faster than django-best
1.55 ± 0.01 times faster than dmr-avg
1.75 ± 0.01 times faster than django-avg
1.98 ± 0.02 times faster than dmr-worst
2.58 ± 0.02 times faster than django-worst