8000 FIX: do not try to help CPython with garbage collection · matplotlib/matplotlib@9f3861f · GitHub
[go: up one dir, main page]

Skip to content

Commit 9f3861f

Browse files
committed
FIX: do not try to help CPython with garbage collection
Matplotlib has a large number of circular references (between figure and manager, between axes and figure, axes and artist, figure and canvas, and ...) so when the user drops their last reference to a `Figure` (and clears it from pyplot's state), the objects will not immediately deleted. To account for this we have long (goes back to e34a333 the "reorganize code" commit in 2004 which is the end of history for much of the code) had a `gc.collect()` in the close logic in order to promptly clean up after our selves. However, unconditionally calling `gc.collect` and be a major performance issue (see #3044 and #3045) because if there are a large number of long-lived user objects Python will spend a lot of time checking objects that are not going away are never going away. Instead of doing a full collection we switched to clearing out the lowest two generations. However this both not doing what we want (as most of our objects will actually survive) and due to clearing out the first generation opened us up to having unbounded memory usage. In cases with a very tight loop between creating the figure and destroying it (e.g. `plt.figure(); plt.close()`) the first generation will never grow large enough for Python to consider running the collection on the higher generations. This will lead to un-bounded memory usage as the long-lived objects are never re-considered to look for reference cycles and hence are never deleted because their reference counts will never go to zero. closes #23701
1 parent 5773bf9 commit 9f3861f

File tree

1 file changed

+0
-9
lines changed

1 file changed

+0
-9
lines changed

lib/matplotlib/_pylab_helpers.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import atexit
66
from collections import OrderedDict
7-
import gc
87

98

109
class Gcf:
@@ -66,10 +65,6 @@ def destroy(cls, num):
6665
manager.canvas.mpl_disconnect(manager._cidgcf)
6766
manager.destroy()
6867
del manager, num
69-
# Full cyclic garbage collection may be too expensive to do on every
70-
# figure destruction, so we collect only the youngest two generations.
71-
# see: https://github.com/matplotlib/matplotlib/pull/3045
72-
gc.collect(1)
7368

7469
@classmethod
7570
def destroy_fig(cls, fig):
@@ -82,14 +77,10 @@ def destroy_fig(cls, fig):
8277
@classmethod
8378
def destroy_all(cls):
8479
"""Destroy all figures."""
85-
# Reimport gc in case the module globals have already been removed
86-
# during interpreter shutdown.
87-
import gc
8880
for manager in list(cls.figs.values()):
8981
manager.canvas.mpl_disconnect(manager._cidgcf)
9082
manager.destroy()
9183
cls.figs.clear()
92-
gc.collect(1)
9384

9485
@classmethod
9586
def has_fignum(cls, num):

0 commit comments

Comments
 (0)
0