From 3325bdeba97860e01c5349716a3133d9a3d38228 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Wed, 5 Sep 2018 15:03:11 -0700 Subject: [PATCH] FIX: squash memory leak for redraws --- lib/matplotlib/transforms.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/transforms.py b/lib/matplotlib/transforms.py index 89942d87e319..9b1ab59f357f 100644 --- a/lib/matplotlib/transforms.py +++ b/lib/matplotlib/transforms.py @@ -111,7 +111,11 @@ def __getstate__(self): def __setstate__(self, data_dict): self.__dict__ = data_dict # turn the normal dictionary back into a dictionary with weak values - self._parents = {k: weakref.ref(v) + # The extra lambda is to provide a callback to remove dead + # weakrefs from the dictionary when garbage collection is done. + self._parents = {k: weakref.ref(v, lambda ref, sid=k, + target=self._parents: + target.pop(sid)) for k, v in self._parents.items() if v is not None} def __copy__(self, *args): @@ -169,7 +173,12 @@ def set_children(self, *children): # parents are destroyed, references from the children won't # keep them alive. for child in children: - child._parents[id(self)] = weakref.ref(self) + # Use weak references so this dictionary won't keep obsolete nodes + # alive; the callback deletes the dictionary entry. This is a + # performance improvement over using WeakValueDictionary. + ref = weakref.ref(self, lambda ref, sid=id(self), + target=child._parents: target.pop(sid)) + child._parents[id(self)] = ref if DEBUG: _set_children = set_children