Hello fellow Djangonistas!
I have posted this also on /r/django but it was suggested to take it here. So here I am.
I am currently trying to evaluate the performance of async Django views in comparison to traditional sync Django views.
For this I created a simple project that has two views:
-
a classic sync view
(see: https://github.com/antonpirker/asyncdjango/blob/main/app/views.py#L21) -
and an async view.
(see: https://github.com/antonpirker/asyncdjango/blob/main/app/views.py#L36)
Both views make two simple queries to the database, one query fetching a list of items and the second query fetching the details of one item.
I have used asyncpg
in the async view and have used psycopg2
in the sync view (without using the ORM of Django for better comparison, because there is async ORM yet).
Then I have run the project once in Gunicorn with the default sync workers to see how long the views take when running in a synchronous Gunicorn process.
- You can try the project with sync Gunicorn here:
https://30d2782āantonpirker-asyncdjango.wdpr.run/
I also have run the project in Gunicorn but using the Uvicorn async workers to see how long the views take when running a asynchronous Uvicorn process.
- You can try the project with async Uvicorn here:
https://5f7f888āantonpirker-asyncdjango.wdpr.run/
(You can also look at the server output when you click on the āLogsā button in the widget on the lower right of the page. You need to be authenticated with your GitHub account to see the logs)
I then have made some load testing on my local machine:
This is the sync
view running in out of the box Gunicorn:
-
Here the moment when the slow down of the view starts: (at ~130 concurrent users)
https://imgur.com/a/LOmnfbl -
And this is when the view starts to throw errors: (at ~310 concurrent users)
https://imgur.com/a/4VsUP6Z
This is the same for the async
view running in Uvicorn workers in Gunicorn.
(Like the Uvicorn documentation tells me that Uvicorn should be run in production)
-
When the slow down of the view starts: (at ~100 concurrent users)
https://imgur.com/a/JU4bXZV -
When the errors start: (at ~280 concurrent users)
https://imgur.com/a/4aW4Bt3
Both are running in a Docker container connecting to Postgres also in a Docker container on my AMD CPU with 8 cores.
So it seems that the async setup can not handle as much concurrent users as the sync setup. Why is this the case?
Should the async setup not be able to serve more concurrent users? Is Uvicorn a bad choice as async server for Django? Do I need to set something in Dockerfile so the container can use all CPU cores?