-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Fix plotting memory leak #9307
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 plotting memory leak #9307
Conversation
12dee0b
to
1a9769a
Compare
@jreback I think this patch is ready for review. Please let me know if you have any questions or suggestions. |
I understand you're referring to this. If so, only |
@sinhrks Yep, it's a subtle bug so I thought it'd be better to convert everything to a safer approach to prevent a reoccurrence. |
Understood. What I'm caring is current impl makes it more difficult to understand the logic... How about:
|
@sinhrks @TomAugspurger can you have a quick look? |
@qwhelan can you squash to a single commit? and pls add a release note referncing the bug? |
@TomAugspurger can you have a look? |
1 similar comment
@TomAugspurger can you have a look? |
I've looked at this a bit. Haven't had a chance to fully digest it since I've never had to deal with this kind of problem before. I'll look more and let you know. It may be something to push for another release.
|
@jreback Hey, sorry about the delay - made the mistake of letting Inbox decide what emails I see. I'll squash it now. Let me know what version I should put it under for the release notes. |
1a9769a
to
795d566
Compare
whats new is now available for 0.16.1 5ebf521 |
795d566
to
2336fb3
Compare
Closing due to better version available in #9814 |
This PR resolves #9003 (and explains matplotlib/matplotlib#3892). The root cause of the memory leak is a reference cycle between
MPLPlot
objects and theAxesSubplot
objects they create.Specifically, a
plotf
function object is stored inax._plot_data
for the purposes of potentially redrawing if the data needs to be resampled. This would be fine if this were a top-level function; however, these are all nested functions that make use ofself
. This means that byplotf
pulls inself.ax
andself.axes
, which point to theAxesSubplot
thatplotf
is being attached to. We therefore have a reference cycle:In order to make the objects collectable, we need to either explicitly break a link or replace it with a weakref. Weakrefs don't work as
AxesSubplot
andMPLPlot
have the same lifetime. Just not using_plot_data
prevents the leak but breaks functionality.The final option as I see it is to change
plotf
to not depend onself
. This works but involves a fair amount of modifications. I elected to make each of theplotf
s top-level functions to make the lack ofself
-dependency explicit. This also required making several other functionsclassmethods
and moving some data fromMPLPlot
to theAxesSubplot
object.The key assumption being made by this change is that either
MPLPlot
objects are discarded immediately after use or we don't want any modifications to theMPLPlot
(e.g., adding errors post-plotting) to be reflected if redrawing. I believe both cases are true but this patch has the potential for behavioral changes ifMPLPlot
objects are regularly being retained and modified.I've also added a memory-leak test to prevent a regression; the test fails as expected if applied without the other commits in this patch.