Hello!
This is related to https://github.com/encode/uvicorn/issues/371 and potentially a duplicate/complementary information, feel free to close if it is deemed to be the case.
I was fooling around with different WSGI and ASGI servers while hacking on a web framework that would support both in the future.
As noted in https://github.com/encode/uvicorn/issues/371, this is indeed a very inefficient scenario, however, what is worse, I found out the time required to turn around the request is at least O(n^2) or worse wrt the payload size.
POSTing some files and multipart forms with curl:
Payload size: 94171344
real 0m5.763s
user 0m0.033s
sys 0m0.012s
```
Payload size: 186054864
real 0m24.183s
user 0m0.018s
sys 0m0.061s
Payload size: 372178858
real 1m37.760s
user 0m0.044s
sys 0m0.152s
So it is not just inefficient loading everything into memory, but something else is going on.
Test case used:
```python
def app(environ, start_response):
status = '200 OK' # HTTP Status
headers = [('Content-type', 'text/plain')] # HTTP Headers
start_response(status, headers)
stream = environ['wsgi.input']
length = 0
while True:
chunk = stream.read(8192)
if not chunk:
break
length += len(chunk)
resp = "Payload size: {}".format(length)
return [resp.encode()]
Running uvicorn==0.11.5 as uvicorn --interface wsgi simple_reader:app.
The issue most probably lies in bytestring concatenation: https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/wsgi.py#L85
chunks.append(chunk)... b''.join(chunks), accumulating in a BytesIO, bytearray_var += ... should all work O(n).
Maybe you can try https://github.com/abersheeran/a2wsgi
It works very well on our production program.
Most helpful comment
The issue most probably lies in bytestring concatenation: https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/wsgi.py#L85
chunks.append(chunk)... b''.join(chunks), accumulating in aBytesIO,bytearray_var += ...should all work O(n).