Opened 3 hours ago
Last modified 3 hours ago
#36674 new Cleanup/optimization
select_related() leaks memory
Reported by: | Jacob Walls | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Calls to select_related()
create nested functions that aren't cleaned up until garbage collection runs:
Borrowed testing strategy from #34865:
-
tests/select_related/tests.py
diff --git a/tests/select_related/tests.py b/tests/select_related/tests.py index 41ed350cf3..252e884d7a 100644
a b class SelectRelatedTests(TestCase): 242 242 FETCH_PEERS, 243 243 ) 244 244 245 def test_memory_leak(self): 246 # todo: factor out a test util 247 import gc 248 249 # Schedule the restore of the garbage collection settings. 250 self.addCleanup(gc.set_debug, 0) 251 self.addCleanup(gc.enable) 252 253 # Disable automatic garbage collection to control when it's triggered, 254 # then run a full collection cycle to ensure `gc.garbage` is empty. 255 gc.disable() 256 gc.collect() 257 258 # The garbage list isn't automatically populated to avoid CPU overhead, 259 # so debugging needs to be enabled to track all unreachable items and 260 # have them stored in `gc.garbage`. 261 gc.set_debug(gc.DEBUG_SAVEALL) 262 263 list(Species.objects.select_related("genus")) 264 265 # Enforce garbage collection to populate `gc.garbage` for inspection. 266 gc.collect() 267 self.assertEqual(gc.garbage, []) 268 245 269 246 270 class SelectRelatedValidationTests(SimpleTestCase): 247 271 """
Gives:
AssertionError: Lists differ: [<cell at 0x10630c940: function object at [148 chars]040>] != [] First list contains 3 additional elements. First extra element 0: <cell at 0x10630c940: function object at 0x1079b8040> + [] - [<cell at 0x10630c940: function object at 0x1079b8040>, - (<cell at 0x10630c940: function object at 0x1079b8040>,), - <function SQLCompiler.get_select.<locals>.get_select_from_parent at 0x1079b8040>]
At a glance, it looks like we can lift get_select_from_parent
to a class method or all the way to module-level without a loss of functionality to address this.
Note:
See TracTickets
for help on using tickets.
Good catch, looks like it could even be a
staticmethod
since it only cares aboutklass_info
.