Hello,
I have written a small script that, I think, demonstrates a memory leak
in savefig. A search of the mailing list shows a thread started by Ralf
Gommers about 2009-07-01 that seems to
cover a very similar issue. I have appended the demonstration script at
the end of this e-mail text.
The demonstration script script sits in a relatively tight loop creating
figures then saving them while monitoring memory usage. A plot of VmRSS
vs. number of loop iterations as generated on my system is attached as
"data.png" (you can create your own plots with the sample script).
Although I have only tested this on Fedora 12, I expect that most Linux
users should be able to run the script for themselves. Users should be
able to comment out the "savefig" line and watch memory usage go from
unbounded to (relatively) bounded.
Can anybody see a cause for this leak hidden in my code? Has anybody
seen this issue and solved it? I would also appreciate it if other
people would run this script and report their findings so that there
will be some indication of the problem's manifestation frequency.
Sincerely,
Keegan Callin
'''Script to demonstrate memory leakage in savefig call.
Requirements:
Tested in Fedora 12. It should work on other systems where
/proc/{PID}/status files exist and those files contain a 'VmRSS' entry
(this is how the script monitors its memory usage).
System Details on Original Test System:
[kee...@grizzly test]$ uname -a
Linux grizzly 2.6.32.9-70.fc12.x86_64 #1 SMP Wed Mar 3 04:40:41 UTC 2010
x86_64 x86_64 x86_64 GNU/Linux
[kee...@grizzly ~]$ gcc --version
gcc (GCC) 4.4.3 20100127 (Red Hat 4.4.3-4)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[kee...@grizzly ~]$ cd ~/src/matplotlib-0.99.1.1
[kee...@grizzly matplotlib-0.99.1.1]$ rm -rf build
[kee...@grizzly matplotlib-0.99.1.1]$ python setup.py build &> out.log
[kee...@grizzly matplotlib-0.99.1.1]$ head -38 out.log
BUILDING MATPLOTLIB
matplotlib: 0.99.1.1
python: 2.6.4 (r264:75706, Jan 20 2010, 12:34:05) [GCC
4.4.2 20091222 (Red Hat 4.4.2-20)]
platform: linux2
REQUIRED DEPENDENCIES
numpy: 1.4.0
freetype2: 9.22.3
OPTIONAL BACKEND DEPENDENCIES
libpng: 1.2.43
Tkinter: no
* TKAgg requires Tkinter
wxPython: no
* wxPython not found
Gtk+: no
* Building for Gtk+ requires pygtk; you must be
able
* to "import gtk" in your build/install environment
Mac OS X native: no
Qt: no
Qt4: no
Cairo: no
OPTIONAL DATE/TIMEZONE DEPENDENCIES
datetime: present, version unknown
dateutil: matplotlib will provide
pytz: 2010b
OPTIONAL USETEX DEPENDENCIES
dvipng: no
ghostscript: 8.71
latex: no
pdftops: 0.12.4
[Edit setup.cfg to suppress the above messages]
[kee...@grizzly matplotlib-0.99.1.1]$ bzip2 out.log
# out.log.bz2 is attached to the message containing this program.
[kee...@grizzly ~]$ python2.6
Python 2.6.4 (r264:75706, Jan 20 2010, 12:34:05)
[GCC 4.4.2 20091222 (Red Hat 4.4.2-20)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> matplotlib.__version__
'0.99.1.1'
'''
# Import standard python modules
import sys
import os
from ConfigParser import SafeConfigParser as ConfigParser
from cStringIO import StringIO
# import numpy
import numpy
from numpy import zeros
# Import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
def build_figure(a):
'''Returns a new figure containing array a.'''
# Create figure and setup graph
fig = Figure()
FigureCanvas(fig)
ax = fig.add_subplot(1, 1, 1)
ax.plot(a)
return fig
_proc_status = '/proc/%d/status' % os.getpid()
def load_status():
'''Returns a dict of process statistics from from
/proc/{PID}/status.'''
status = {}
with open(_proc_status) as f:
for line in f:
key, value = line.split(':', 1)
key = key.strip()
value = value.strip()
status[key] = value