Description
Hi,
It appears that Django's ORM is leaking quite a lot into RAM, and I'm not exactly sure why I can't find anything about this problem.
Let's start with the fix. Wrapping all my tasks with this (largely inspired by Django Channels) resolved the issue:
from django.db import close_old_connections, reset_queries
def plug_psycopg_leak(func):
@wraps(func)
def wrapper(*args, **kwargs):
close_old_connections()
reset_queries()
try:
return func(*args, **kwargs)
finally:
close_old_connections()
reset_queries()
return wrapper
This quickly became an issue on my app because it stores big blobs in DB and they basically were never freed from memory.
Note — Those blobs make sense in my app because they're only read/written from Procrastinate so I don't really care how much slower the operation is in comparison to storing that in a S3 bucket, and as a bonus I don't need a S3 bucket
This is how my memray flamegraph --leaks
diagnostic looked like before the fix:
Now all the cursors get freed and I don't see a spot of psycopg in my flamegraph anymore.
The weird thing is, it looks like this leak only happens on my production server. When running on my local machine, the leak is nowhere to be seen in my flamegraph. Which I guess is consistent with the fact that no one reported this issue?
Before digging any deeper, I'd like to get the point of view from the Procrastinate team on this. Like, what is the intended behavior in regards to clearing the Django connections? How come Channels needs it and Procrastinate doesn't mention it?
Thanks!