WSGIMiddleware overhead
gaganpreet opened this issue · comments
I'm exploring the feasibility of moving an existing Flask app to FastAPI while running the old Flask app using the WSGIMiddleware.
I've been running some performance tests and there's a very significant overhead that WSGIMiddleware brings to the mix. I wrote a small demo here.
This is how I run the server:
uvicorn main:app --port 8000 --no-access-log --workers 1
There are two endpoints: /users_fastapi
(direct, no middleware) and /users_flask
(wsgi middleware). Both endpoints query some dummy data from the in-memory db and return it as a response.
$ wrk http://127.0.0.1:8000/users_fastapi
Running 10s test @ http://127.0.0.1:8000/users_fastapi
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 568.68ms 68.02ms 637.11ms 95.32%
Req/Sec 12.06 7.11 20.00 36.21%
171 requests in 10.01s, 16.15MB read
Requests/sec: 17.08
Transfer/sec: 1.61MB
$ wrk http://127.0.0.1:8000/users_flask
Running 10s test @ http://127.0.0.1:8000/users_flask
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.24s 157.89ms 1.56s 77.03%
Req/Sec 7.58 5.52 20.00 64.06%
74 requests in 10.01s, 6.99MB read
Requests/sec: 7.39
Transfer/sec: 714.88KB
The direct route has a throughput of 17.08 reqs/s, and the one behind wsgi middleware only goes up to 7.39, which is a significant difference.
I'm looking at the middleware and trying to figure out if there's room to reduce overhead, however, any inputs or ideas are much appreciated.
Maybe you can get a better comparison by testing the performance of the original flask.
You are welcome to submit any PRs that improve performance. Here's a performance benchmark I just ran.
$ pytest ./benchmark.py -s
=================================================================================== test session starts ===================================================================================
platform win32 -- Python 3.9.6, pytest-7.0.1, pluggy-1.0.0
rootdir: C:\Users\aber\Documents\GitHub\a2wsgi
plugins: anyio-3.5.0, asyncio-0.11.0, cov-3.0.0
collected 6 items
benchmark.py
Name Average Time
pure-ASGI 0.00030796286.
a2wsgi-WSGIMiddleware 0.0008904933199999999.
uvicorn-WSGIMiddleware 0.00062742427.
asgiref-WsgiToAsgi 0.00141565296.
pure-WSGI 0.00023801917.
a2wsgi-ASGIMiddleware 0.0008830748.
Maybe you can get a better comparison by testing the performance of the original flask.
I tried this.
gunicorn main:flask_app --bind=:8000 -w 1
$ wrk http://localhost:8000/users_flask
Running 10s test @ http://localhost:8000/users_flask
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 414.07ms 43.31ms 480.73ms 94.07%
Req/Sec 13.61 7.62 30.00 70.07%
236 requests in 10.01s, 22.29MB read
Requests/sec: 23.58
Transfer/sec: 2.23MB
At 23.58 reqs/s, pure Flask is even faster than the ASGI implementation. This is not a fair comparison of ASGI vs WSGI, as the ASGI code is running synchronous code.
You are welcome to submit any PRs that improve performance.
I haven't found anything yet to improve performance, I'll spend some time this weekend and see what's possible.