-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Refs #16022 - Use a weak reference for file field memory optimization #15592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Hi @massover — Thanks again for this: good stuff.
So — yes this is the tricky bit — if you have only the reference to the It's an open question as to how often folks would hit this: i.e. in real-life is the I like the idea of allowing the option to use a Without new API (but with new docs...) we could subclass In summary:
Both the latter two need wider discussion/agreement I think. Are you happy to push forward on the first part at least? Thanks again! 🏅 |
Yes I can push forward on the first part. Thank you for the review! |
@carltongibson This pr now includes a
Lastly, I updated the little example project with a command that shows the data sizes where the reference cycle starts to matter
|
I've encountered this problem, I think. In my scenario, I see extremely high memory consumption -- something like 10 to 25 times the memory used compared to the original file size -- but only when our logging middleware from django-request-logging is in play. If I remove the middleware entirely, then memory consumption is about 1.5x file size. If I disable logging on the upload view method using the |
Ticket
I believe that the tests should all pass. However, I have added a test to my example project that fails. I believe this is breaking if the weak ref is lost while trying to use FileField.save. The documented api itself is cyclic which is going to be tricky.
Let me show the performance difference I observed.
before:
(the drop is a new deployment)
after:
(the drop is a new deployment)
For my application, the memory utilization and latency saw such huge improvements. The memory utilization is evident in the graphs. The latency improvements come mostly in P99 (requests that are unlucky to catch gc). As @carltongibson notes, it's not a leak per se. It is eventually garbage collected. However, in my application, we were building up so much gen 2 garbage that when gc eventually starts, the latency takes a huge hit. With no reference cycle, there is less garbage.
Since this seems like a breaking change as far as I can see, I would hope that some other people can try this out and see if it makes a noticeable difference in their application (as it did for mine). Here is some code that should patch:
The way to verify it would be using your existing memory metrics (!) or using something like psutil in code (such as a middleware) and printing it.
I get that we all choose python and make tradeoffs on performance in this interpreted garbage collected language. For this improvement, I'm looking for data next, not to imply that because it made a huge impact on my project that it's the way to go. It would be nice if someone else could give their input on a real project! As an example, I believe that something like the following could be affected:
If the api can't break, and we'd like to move forward, here is a suggestion