ManyToMany relationships create circular references
|Reported by:||Andrea Corbellini||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.2|
|Cc:||Andrea Corbellini||Triage Stage:||Unreviewed|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
Here is how you can reproduce the problem:
- First, download the attached tar.gz which contains a simple Django project with an app. The important file is models.py, that contains the m2m relationship.
- Open a Python console and enable DEBUG_SAVEALL in the GC:
>>> import gc >>> gc.set_debug(gc.DEBUG_SAVEALL)
- Import the 'models' module from the Django app:
>>> from testproj.testapp import models
- Run a full collection and check the garbage:
>>> gc.collect() 6 >>> gc.garbage [..., <class 'django.db.models.fields.related.Meta'>, ...]
In most of the cases this isn't a problem, because the GC without DEBUG_SAVEALL automatically deletes such objects. However this becomes an issue when you want to disable the garbage collector to increase performances a bit. This problem is caused by the fact that creating a Python's new-style class creates circular references and in fact 'Meta' is a new-style class.
I see that this problem occurs for almost every operation that involves a many-to-many relationships: the Meta class is created (sometimes more than one time) and then is deleted. To avoid the problem, I think that Meta shouldn't be a temporary class, but should be saved somewhere in the model, so that it will never be deleted till the interpreter exits (or the model is destroyed). Using a dictionary instead of a class may solve the problem too.