Django App memory usage

fifdeePRO

a year ago

Hey,
I have a Django app (ASGI + uvicorn), which uses some image processing (done with AWS Lambda). In order to send those images for processing, my Django app has to create uploaded image models for current user and accepts up to 400MB post request containing images. I thought I had a memory leak as after posting such a big request app memory usage in railway metrics goes up (which is completely normal), but remains at high level even after completing the job related to request. I implemeted some logging with tracemalloc to see where those memory leaks are, but it turned out that there are no memory leaks and in tracemalloc logs current memory usage goes back to low level after completing request. Is there any option for the railway app to behave more dynamically when it comes to memory usage, so it does not keep high memory consumption levels all the time?
Thanks for help.

Solved

15 Replies

a year ago

A tracemalloc does not give the full picture for the entire container memory usage, the best option here is to not buffer the uploads into memory, you would want to stream them directly to AWS or to disk and then stream to AWS.


fifdeePRO

a year ago

Thanks for reply. Streaming directly to AWS will not work for big requests size as there is a limit of 6 MB payload. I am also performing image verification before sending to AWS. I will do some tries on saving on disk in chunks and uploading to AWS, and perform verifiaction in AWS lambda.


a year ago

Sounds good! if your files never get fully loaded into memory then there's no room for memory leaks!


fifdeePRO

a year ago

Seems like not Railway specific after all, but maybe someone is using Django. The problem is that even after making sure that files are uploaded as multipart/form-data and they reside in request.FILES as temporary uploaded files, memory consumption goes up. Tracemalloc shows Python built-in tempfile.py which occupies memory and unfortunately that memory is still occupied after finishing request. Quite confusing, as disk space should be used and not memory.


a year ago

Yep, for sure not Railway specific in any way.

files are uploaded as multipart/form-data and they reside in request.FILES as temporary uploaded files

That alone does not guarantee files aren't buffered entirely into memory.


fifdeePRO

a year ago

I will have to figure out a way of client side upload to AWS then. It should be possible with pre-signed URLs.


a year ago

Or don't buffer the entirety of the files into memory and instead stream the upload directly to disk.


fifdeePRO

a year ago

Or don't buffer the entirety of the files into memory and instead stream the upload directly to disk.

But how? I don't even do anything with the files and I see they occupy memory at the very beginning of the view, Django is managing the upload process and they shouldn't take memory as temporary uploaded files (according to docs).


a year ago

If django is not behaving how you want it to you might need to manually handle the file uploads so that you can properly implement read and write streams.


Status changed to Solved railway[bot] about 1 year ago


fifdeePRO

a year ago

Here is a problem description I posted on stackoverflow: https://stackoverflow.com/questions/78339166/python-django-asgi-memory-leak-updated

One thing to mention in terms of Railway is the fact that memory is not being released when restarting workers using this option: "hypercorn --workers 5 --max-requests 50 --max-requests-jitter 25".
I checked on Render.com and restarting workers releases memory there.


a year ago

Despite the clearly different behaviour between Render and Railway, this would still not be an issue with Railway, It is solely up to your app to release memory. But most preferably you don't put stuff into memory that doesn't need to be in memory.


fifdeePRO

a year ago

For me Railway and Render are PaaS for hosting my web app. I don't know the specifics behind it, that's the point of using such platforms, right? I can only compare results. And restarting workers should release memory as it does when using Render, no matter how my app behaves. And if you looked at stackoverflow link I posted above, you would see that currently all data that go through Django web server are simple json requests and responses from AWS Lambda.


a year ago

Railway will only ever run your code as-is, they will not try to magically monkey patch your code for you like render may be doing.

Whatever behavior you are seeing is the behavior of your code and in this case, has nothing to do with the platform.

But I do get it, doesn't happen locally and doesn't happen on Render does make it seem like a Railway issue, and believe me I've been in your shoes and spent so much wasted time blaming Railway for my own memory problems once before. So please believe me when I say that this is not a platform issue, I've had to learn that fact myself before too.


fifdeePRO

a year ago

At least I managed to minimize the problem so it'll take thousands of requests to fill the memory. If I find some time I'll try with some kind of simplest app - hosting -> checking for memory leaks -> adding libraries one by one -> checking for memory leaks and so on.


a year ago

Sounds good. But for now, ill mark this as solved, if you have any platform issues or platform questions, please feel free to open a new post!


Django App memory usage - Railway Help Station