uvicorn: Memory leak when using request.state
Discussed in https://github.com/encode/starlette/discussions/1748
<div type='discussions-op-text'>Originally posted by galkahana July 10, 2022 Hi, I noticed that setting properties on request.state results in memory leak.
Originally an issue I reported in fastapi, it seems that the following server definition will cause memory usage to grow on every request:
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette.requests import Request
async def homepage(request: Request):
request.state.test = [x for x in range(999999)]
return JSONResponse({'hello': 'world'})
app = Starlette(routes=[
Route('/', homepage),
])
The array set as the test property of request.state is never released. There’s a workaround that I can use to resolve this by setting the the property to none at the end of the request - request.state.test = None.
I created a repo to demonstrate the issue here.
Figured i’ll report, so at least if someones getting a memory leak, this can help in possibly finding the cause.</div>
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 19 (16 by maintainers)
The bug is confirmed to be on
uvicorn. The behavior doesn’t happen withhypercorn.Since you’re sharing… I’m going to give you more information…
The HTTP protocol object is not freed, as you said. It contains a reference cycle. The garbage collector is not able to clean it in time. The object goes to the third generation. The third generation needs a condition to be met to be cleaned (see Python docs), which takes time.
I’ve found the cycle, and removed the cycle.
The issue didn’t disappear. I’m trying to find if there’s another cycle.
I’m going to provide a full report when I’m able to fix this issue. @graingert (helping me a lot on this 🙏) and @euri10 are aware of everything that I’ve been doing.
Although this is an issue, and we need to solve it, I’ve confirmed that is an issue that
uvicornalways had (since the framework was created). Also, it doesn’t affect everybody in the same way, and the memory is cleaned at some point, it’s just that it takes some time.That said, it’s still my priority.
Alright, I gave it another try and I compared with h11 protocol that was well managing its memory, so in the end it seems that the way httptools decorates the protocol, it keeps a bunch of references to it in each decorated method and by stop referencing it during disconnection you remove the cyclic reference, so the garbage collector can do it’s work 😃
No problem, I’m glad to be able to help 🙂
Humberto solved the issue. Thanks @humrochagf 🙏
The fix will be available in
uvicorn0.18.3.I’ll be a bit away for the next two weeks, so if you solve it, feel free to create a PR. 🙏
If not, when I’m back I’ll continue on it.