-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix LayoutGrid leaks #25853
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
Fix LayoutGrid leaks #25853
Conversation
While the above comment claims that these variables are useful, they are not added to the solver nor added to any constraints, so they cannot contain any useful information. They are only really used for the `__repr__`, which can be changed to the actually-used Variables instead.
Internally, the parent is only used in `__init__`, so doesn't need to be saved as an attribute. Externally, the constrained layout code needs the parent only for subfigure margins, but we have the parent gridspec available directly to use. The `LayoutGrid` stores its children in a NumPy array, and saving the parent causes a reference cycle. Apparently having one reference in a C-level NumPy array causes Python to not realize it can garbage collect the cycle, causing all `LayoutGrid` and its children to leak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice investigation! I verified that this works locally.
I'm wondering if leaks like this are worth adding to the test suite to make sure the reference cycles don't get reintroduced? We could depend on objgraph for this, or do some of our own verification asserting LayoutGrid
isn't in gc.get_objects()
So was it the second paragraph that was the memory leak or the first paragraph also? Thanks! |
The second paragraph is the leak; the first is just motivation for making the change this way instead of trying to break the cycle after layout manually. |
…853-on-v3.7.x Backport PR #25853 on branch v3.7.x (Fix LayoutGrid leaks)
Thanks for fixing this - sorry I didn't have time to investigate, but suspect I'd never have figured this out. I'm happy with the fix, however, this does seem to me like an upstream bug? Is it really a thing that object |
PR summary
Internally, the
LayoutGrid
parent is only used in__init__
, so doesn't need to be saved as an attribute. Externally, the constrained layout code needs the parent only for subfigure margins, but we have the parent gridspec available directly to use.The
LayoutGrid
stores its children in a NumPy array, and saving the parent causes a reference cycle. Apparently having one reference in a C-level NumPy array causes Python to not realize it can garbage collect the cycle, causing allLayoutGrid
and its children to leak.Removing the
parent
attribute removes the cycle and fixes the leak.Additionally, I've removed extraneous
Variable
s that are not used for anything other than__repr__
, but they are not actually filled with anything real there. In the example from #25819, this saves 16Variable
s per iteration.Fixes #25819
PR checklist