You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Memory leak when plotting multiple figures with the macOS backend #19769
If you throw a plt.pause(.1) into the loop does the memory get cleared? We have seen issues where if you are creating figures that in turn create GUI objects at the c/c++/objectivec level. Depending exactly how the event loops work under the hood we can have the situation:
create figure (allocate memory)
destroy the figure (do not actually destroy the GUI objects, but just tell the event loop you would like to destroy those objects)
the event loop notices your request, makes sure it is fully safe, tears down the GUI object and releases the memory
but, if you are running this in a tight loop like the example you are never letting the event loop run so you have N GUI windows hanging out waiting to be cleared.
I did a bit of digging, and the back reference graphs I get tracing from Figure have only one difference between Agg and macosx. FigureManagerMac has a ref count of 3, whereas FigureManagerBase a ref count of 2.
So I suspect that a reference to FigureManagerMac is hanging around somewhere in the C layer, because it's not showing up on the python reference graphs. I guess this is probably somewhere in _macosx.FigureManager.
I don't think I have the knowledge to track this down in the C layer (if that's indeed where it is), but FWIW this issue is present at least back to Matplotlib v3.2.2.
There is a reference held in the ObjC side on the Window class. It is taken in initWithContentRect and removed in dealloc. Maybe there is something related to the lifecycle issue in #21788.
And the chain for the canvas is below. It looks like there might be an issue with TimerMac being in a circular reference with a __del__ defined (in red below)? Again I'm far from an expert, but might be worth someone who understands the mac code checking that TimerMac (fully implemented in the C layer) doesn't have any memory issues?
Activity
jklymak commentedon Mar 25, 2021
tgrohens commentedon Mar 25, 2021
gc.collect()after theplt.close()call.tacaswell commentedon Mar 25, 2021
If you throw a
plt.pause(.1)into the loop does the memory get cleared? We have seen issues where if you are creating figures that in turn create GUI objects at the c/c++/objectivec level. Depending exactly how the event loops work under the hood we can have the situation:but, if you are running this in a tight loop like the example you are never letting the event loop run so you have N GUI windows hanging out waiting to be cleared.
tgrohens commentedon Mar 26, 2021
Hey,
Nope, even with a
plt.pause(1.0)thrown in I still get the same behavior.anntzer commentedon Mar 26, 2021
Perhaps try using
objgraph.show_growth()(https://mg.pov.lt/objgraph/#memory-leak-example) to see whether it's Python objects leaking or (Obj)C ones?tgrohens commentedon Mar 26, 2021
I certainly can do that.
Here's the result for the last two iterations of the loops (deltas are the same from one iteration to the next), with
limit=25:It does look like matplotlib objects to me.
dstansby commentedon Dec 21, 2021
I did a bit of digging, and the back reference graphs I get tracing from
Figurehave only one difference betweenAggandmacosx.FigureManagerMachas a ref count of 3, whereasFigureManagerBasea ref count of 2.So I suspect that a reference to
FigureManagerMacis hanging around somewhere in the C layer, because it's not showing up on the python reference graphs. I guess this is probably somewhere in_macosx.FigureManager.Here's the code I'm using if anyone's interested:
dstansby commentedon Dec 21, 2021
I don't think I have the knowledge to track this down in the C layer (if that's indeed where it is), but FWIW this issue is present at least back to Matplotlib v3.2.2.
QuLogic commentedon Dec 22, 2021
Is the reference count the same with Qt backends?
There is a reference held in the ObjC side on the
Windowclass. It is taken ininitWithContentRectand removed indealloc. Maybe there is something related to the lifecycle issue in #21788.dstansby commentedon Jan 27, 2023
Coming back to this, the growth I'm getting with the code in #19769 (comment) is
And the chain for the canvas is below. It looks like there might be an issue with

TimerMacbeing in a circular reference with a__del__defined (in red below)? Again I'm far from an expert, but might be worth someone who understands the mac code checking thatTimerMac(fully implemented in the C layer) doesn't have any memory issues?greglucas commentedon Apr 27, 2023
This was fixed by: #23059