-
-
Notifications
You must be signed in to change notification settings - Fork 7.7k
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
Closed figures linger in memory #8519
Comments
The underlying issue is that there are circular references between the figure and the axes. We could make some of those weak refs (and patch over it with properties), but that would be a pretty big effort to find all of the references back and forth. However, if we did this we would put a bunch of extra work on the user to make sure stuff did not get erroneously garbage collected. I am not sure that adding a kwarg to close is any clearer to users than having to do the gc them selves. |
Right, that does sound like a tangled ball of wool.
I appreaciate the messiness of a kwarg (or rcparam) like that. On the other hand, it would have saved me an afternoon of poking around with memory_profile if there was something that signaled "here be dragons, and here's the one official way to hack around them". Should I write a paragraph for the docs? |
A paragraph for the docs would be appreciated. I am not sure where the best place to put it is though. Maybe in the faq section? |
Maybe this wouldn't help, but: Suppose that when closing a figure we walked through the hierarchy of children, and for each child artist, set its figure reference to None. Would that break the circles? |
Take it a step further. When *clearing* a figure, do that, and when
clearing an axes, do the same for all axes references in the artist. That
might do the trick.
Would need to make sure any events are fired before cleaning up, but that
should help disentangle the knot a bit.
The other big circular reference is the figure manager/canvas/figure cross
reference.
…On Apr 21, 2017 6:25 PM, "Eric Firing" ***@***.***> wrote:
Maybe this wouldn't help, but: Suppose that when closing a figure we
walked through the hierarchy of children, and for each child artist, set
its figure reference to None. Would that break the circles?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#8519 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-Axm5tCINC982eWFsu3pfKC21zniks5rySzsgaJpZM4NDAbh>
.
|
What is the best practice, if you are looping and generating a large number of images with matplotlib, what is the solution? Is there a way to just force matplotlib to unload any memory that it has? So far, the only way I can do this is put each call to matplotlib in a separate process, but I would like to think I could generate multiple plots in a single process (or notebook). I've tried various combos of .clf() .close(figure) and python del's but it still leaks and eventually crashes. |
From what I found back then, it helps to manually trigger garbage collection after closing each figure, with |
I am forcing a garbage collect, but no luck. I still run out of memory and crash. So far the only workarounds I have are:
|
`gc.collect()` won't work because the figure references are held in the
pyplot state manager. The correct course of action is to reuse the figure
objects.
…On Sun, Apr 14, 2019 at 12:15 PM Jeff Heaton ***@***.***> wrote:
I am forcing a garbage collect, but no luck. I still run out of memory and
crash. So far the only workarounds I have are:
- Each figure in its own process (this works the best)
- Reuse figures as much as possible (just pass them around and update
subplots and other items inside of already allocated objects. (this also
works well, there are still leaks, but I can usually keep the ship afloat
long enough to finish)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#8519 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-L5nZrJAeJyGCEOdadQINRCdM6Xtks5vg1QigaJpZM4NDAbh>
.
|
so closing a figure doesn't remove references to it in the pyplot state manager? |
no, it does, so long as the figure was created through the pyplot
mechanisms, closing it should remove it from the state manager. But, the
typical scenario when someone reports a "memory leak" in matplotlib is when
they just let the figure object go out of scope, and wonder why
`gc.collect()` doesn't do anything.
…On Mon, Apr 15, 2019 at 9:57 AM Jody Klymak ***@***.***> wrote:
so closing a figure doesn't remove references to it in the pyplot state
manager?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#8519 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-FvG57zzmGuNdjTLDKS4FRGAMntBks5vhIVVgaJpZM4NDAbh>
.
|
Turn the interactive mode off before running any of your loops. It did the trick for me. |
Memory leaks due to Matplotlib circular dependencies: matplotlib/matplotlib#8519
What happens if you do not include a legend in your plots? See issue #19345. |
What worked for me was to use fig.savefig() instead of plt.savefig(). And then close the figure with plt.close(). |
@analkumar2 OP says they closed it and it still didn't work |
@adeeb10abbas The issue is still open. With python 3.6.9, matplotlib 3.3.4 , Ubuntu 20.04, if you run the following code:
You will run out of RAM very soon. You've to use fig.savefig() instead of plt.savefig() to avoid the memory leak. |
@analkumar2 I just tested with python 3.8, matplotlib 3.3.4, Ubuntu 20.04 and was not able to reproduce your issue. There was no memory leak. Can you update your python version and see if it works? |
I'm going to close this, because I don't think every memory leak issue should be put in the same issue. #8519 (comment) is quite different from he original post, and I think it is confusing to conflate them. Feel free to re-ope if the original post is still leaking. However, I couldn't make that run on my machine, so I'm not sure how relevant it is 4 years later. |
If you are doing batch work setting matplotlib.use('agg') may also help. With some version of Qt if you never spin the event loop we end up with many windows which are "closed", but still exist and are waiting for the Qt main loop to spin so they can finish deleting themselves! |
Sorry. Even I cannot reproduce this now. I have not updated my system or any of the packages. I should have saved the memory profiler output when I was having the issue. |
Memory leaks due to Matplotlib circular dependencies: matplotlib/matplotlib#8519
I am facing a similar issue on Ubuntu 18.04, python 3.8.12, matplotlib 3.4.2. The program consumes all RAM and SWAP and then crashes. any ideas? Thanks in advance. Indicative code is below:
|
Please open a new issue with a self-contained minimal reproducible example. |
@vishalmhjn did you try it with |
I can reproduce the issue with python 3.7.9 and matplotlib 3.5.1 on Windows 10 version 20H2. Observing the task manager, you can clearly see memory building and after nearly 1-1.5 GB of build up the following error shows "Fail to create pixmap with Tk_GetPixmap in TkImgPhotoInstanceSetSize" |
It's interesting. I never faced this issue on my old laptop but was surprised when I encountered it on my new laptop. So I had to go back and check the matplotlib version on old laptop which was 3.3.4. So I tried to reproduce the above error on windows 10 20H2, python 3.7.9 and matplotlib 3.3.4 on my new laptop and surprisingly I wasn't able to. Looks like there is some issue with the latest release of matplotlib, I suggest using matplotlib version 3.3.4 if anyone is facing this issue. Hoping this helps in other issues as well. |
@Prajval-1608 can you please open a new issue with all the relevant details? Perhaps most pertinent would be to also include what backend you are using.... |
I'm actually going to lock this to stop the me-too comments on a five-year-old issue. If you think you have a memory leak with a recent matplotlib version that is reproducible, please fill out a new issue with all the relevant information requested. Thanks! |
tl;dr: When I repeatedly create a large figure, save it, and close it, memory usage keeps growing.
Over at this discussion about when MPL should trigger garbage collection, @efiring had some lingering doubts about the chosen solution:
I ran into such a case today, when my batch job filled up 60G of RAM over night.
I repeatedly create a large figure, save it, then close it. If I don't manually call
gc.collect()
after closing each figure, memory consumption saturates at around 10x of what an individual figure needs. In my case, with several fairly complex figures, this was enough to fill a big machine.Since this is not obvious from the docs, I think there should be an official way to go back to more aggressive GC for cases like this where the trade-off discussed at #3045 fails. Maybe
close(force_gc=True)
?Code for reproduction
Matplotlib version
The text was updated successfully, but these errors were encountered: