memory leak in canvas.draw() in TkAgg

I'm afraid your change didn't help (I only applied the patch to
lib/matplotlib/text.py; the cbook.py change appeared to only affect
whitespace).

However, the memory leak is smaller using the svn trunk than in
matplotlib 1.0.0. Also, calling subplot.clear() makes the leak worse in
matplotlib 1.0.0 but not on the trunk.

Here are my results in detail. Before each run I show a few lines of
code from:
<http://www.astro.washington.edu/users/rowen/python/matplotlibMemoryLeak.

MemoryLeaker's _updateTimeAxis method. Note that the third column is a
measure of the leak rate and I hold off measuring the leak rate for few
seconds to give the application a chance to fully load.

-- Russell

matplotlib 1.0.0

        self.subplot.set_xlim(tMin, tMax)
# self.subplot.clear()
        self.canvas.draw()
rowen:Python bugs rowen$ python matplotlibMemoryLeak.py
time rss memory mem/sec
(sec) (kb) (kb/sec)
   0.0 27676 nan
   5.0 28980 nan
  10.1 29084 20.6
  15.1 29172 19.0
  20.1 29268 19.1
  25.2 29368 19.3
  30.2 29464 19.2
  35.2 29564 19.4
  40.2 29660 19.3
  45.2 29764 19.5

        self.subplot.set_xlim(tMin, tMax)
        self.subplot.clear()
        self.canvas.draw()
rowen:Python bugs rowen$ python matplotlibMemoryLeak.py
time rss memory mem/sec
(sec) (kb) (kb/sec)
   0.0 27696 nan
   5.1 29012 nan
  10.2 29152 27.5
  15.2 29292 27.7
  20.2 29436 28.0
  25.3 29580 28.1
  30.4 29728 28.3
  35.4 29876 28.5
  40.5 30024 28.6
  45.5 30160 28.4
  50.6 30308 28.5

matplotlib svn trunk rev8836

        self.subplot.set_xlim(tMin, tMax)
# self.subplot.clear()
        self.canvas.draw()
rowen:Python bugs rowen$ python matplotlibMemoryLeak.py
time rss memory mem/sec
(sec) (kb) (kb/sec)
   0.0 27664 nan
   5.0 28864 nan
  10.0 28880 3.2
  15.1 28884 2.0
  20.1 28896 2.1
  25.1 28908 2.2
  30.1 28916 2.1
  35.1 28928 2.1
  40.2 28940 2.2
  45.2 28948 2.1

        self.subplot.set_xlim(tMin, tMax)
        self.subplot.clear()
        self.canvas.draw()
time rss memory mem/sec
(sec) (kb) (kb/sec)
   0.0 27684 nan
   5.1 28856 nan
  10.1 28856 0.0
  15.1 28856 0.0
  20.1 28864 0.5
  25.2 28872 0.8
  30.2 28880 1.0
  35.2 28884 0.9
  40.2 28892 1.0
  45.2 28900 1.1
  50.2 28920 1.4
  55.3 28924 1.4
  60.3 28932 1.4
  65.3 28940 1.4

After applying your patch to svn trunk rev8836:
--- lib/matplotlib/text.py (revision 8819)
+++ lib/matplotlib/text.py (working copy)
@@ -143,6 +143,9 @@
    Handle storing and drawing of text in window or data coordinates.
    """
    zorder = 3

···

+
+ cached = maxdict(50)
+
    def __str__(self):
        return "Text(%g,%g,%s)"%(self._y,self._y,repr(self._text))

@@ -168,7 +171,6 @@
        """

        Artist.__init__(self)
- self.cached = maxdict(5)
        self._x, self._y = x, y

        if color is None: color = rcParams['text.color']

        self.subplot.set_xlim(tMin, tMax)
# self.subplot.clear()
        self.canvas.draw()
rowen:Python bugs rowen$ python matplotlibMemoryLeak.py
time rss memory mem/sec
(sec) (kb) (kb/sec)
   0.0 27656 nan
   5.0 28852 nan
  10.1 28864 2.4
  15.1 28876 2.4
  20.1 28888 2.4
  25.1 28908 2.8
  30.1 28916 2.6
  35.1 28924 2.4
  40.2 28936 2.4

        self.subplot.set_xlim(tMin, tMax)
        self.subplot.clear()
        self.canvas.draw()
rowen:Python bugs rowen$ python matplotlibMemoryLeak.py
time rss memory mem/sec
(sec) (kb) (kb/sec)
   0.0 27652 nan
   5.0 28836 nan
  10.0 28852 3.2
  15.1 28852 1.6
  20.1 28872 2.4
  25.1 28880 2.2
  30.1 28900 2.6
  35.1 28904 2.3
  40.2 28912 2.2
  45.2 28920 2.1
  50.3 28928 2.0

In article <4D028BC7.1000304@...31...>,
Michael Droettboom <mdroe@...31...>
wrote:

I think I'm on to something -- it seems that text layout information has
a cyclical reference that prevents the Text object from being freed.

Can you apply the attached patch and let me know if it solves your issue?

Mike

On 12/10/2010 02:19 PM, Russell E. Owen wrote:
> You may have already seen this in the general mailing list, but I've
> found what I think is a serious memory leak in matplotlib 1.0.0: it
> leaks memory every time canvas.draw() is called, at least when using
> TkAgg on unix and Mac.
>
> Admittedly many graphs do not need canvas.draw() to be called repeatedly
> (which I suspect is how it has survived this long). This came up in the
> context of a strip chart widget, where I am changing the x/time axis
> limits regularly and calling canvas.draw() so that the change is visible.
>
> I submitted ticket 3124990 with a very simple demo script:
> <https://sourceforge.net/tracker/?func=detail&atid=560720&aid=3124990&gro
> up_id=80706>
> (you can disable the setting the x limits if you want to see the leak in
> its purest form, but then nothing changes visually on the graph).
>
> I just wanted to be sure folks know about it in hopes somebody might
> have an idea how to fix it. I have not tried any other back ends.
>
> -- Russell
>
>
> ----------------------------------------------------------------------------
> --
> Oracle to DB2 Conversion Guide: Learn learn about native support for
> PL/SQL,
> new data types, scalar functions, improved concurrency, built-in packages,
> OCI, SQL*Plus, data movement tools, best practices and more.
> http://p.sf.net/sfu/oracle-sfdev2dev
> _______________________________________________
> Matplotlib-devel mailing list
> Matplotlib-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
>

--
Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA

---------------------------------------------------------------------
Index: lib/matplotlib/cbook.py

--- lib/matplotlib/cbook.py (revision 8819)
+++ lib/matplotlib/cbook.py (working copy)
@@ -1109,9 +1109,10 @@
         dict.__init__(self)
         self.maxsize = maxsize
         self._killkeys = []
+
     def __setitem__(self, k, v):
         if k not in self:
- if len(self)>=self.maxsize:
+ if len(self) >= self.maxsize:
                 del self[self._killkeys[0]]
                 del self._killkeys[0]
             self._killkeys.append(k)
Index: lib/matplotlib/text.py

--- lib/matplotlib/text.py (revision 8819)
+++ lib/matplotlib/text.py (working copy)
@@ -143,6 +143,9 @@
     Handle storing and drawing of text in window or data coordinates.
     """
     zorder = 3
+
+ cached = maxdict(50)
+
     def __str__(self):
         return "Text(%g,%g,%s)"%(self._y,self._y,repr(self._text))

@@ -168,7 +171,6 @@
         """

         Artist.__init__(self)
- self.cached = maxdict(5)
         self._x, self._y = x, y

         if color is None: color = rcParams['text.color']
---------------------------------------------------------------------
------------------------------------------------------------------------------
Oracle to DB2 Conversion Guide: Learn learn about native support for PL/SQL,
new data types, scalar functions, improved concurrency, built-in packages,
OCI, SQL*Plus, data movement tools, best practices and more.
http://p.sf.net/sfu/oracle-sfdev2dev
---------------------------------------------------------------------
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel