There have been some complaints about leaking FT2Font objects: it
seems that if you make too many plots, mpl crashes because it has
opened the same font files too many times. I think this is a symptom
of the same GUI memory leaks that have been discussed earlier.
Inspired by http://www.python.org/~jeremy/weblog/030410.html, I wrote
a script that lists what kind of objects are leaking. You need a
debugging build of Python to use it, and have to compile all
extensions for the debugging build. To call the script, give the
backend on the command line, as in "python whatsleaking.py Agg".
Here is the output for Agg:
--- 0
--- 1
{<type 'str'>: 1, <type 'dict'>: 1, <type 'int'>: 24}
--- 2
{<type 'dict'>: 1, <type 'int'>: 24}
--- 3
{}
--- 4
{}
--- 5
{}
--- 6
{}
--- 7
{}
--- 8
{}
--- 9
{}
On round 0 there is never any output, but the script memorizes how
many objects of each type exist. On round 1 there is one more string,
one more dict, and 24 more ints. On round 2, in addition to these,
there is one more dict and 24 more ints. Thereafter the numbers stay
constant so there is no output. (There is also some code for chasing
references to FT2Font objects, but it's commented out.)
So pure Agg is not leaking. The output for TkAgg is different:
--- 0
--- 1
{<type 'set'>: 3, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'Interval'>: 16, <type 'tuple'>:
208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type 'function'>: 1,
<type 'str'>: 253, <type 'dict'>: 395, <class 'matplotlib.cbook.maxdict'>: 34,
<type 'BinOp'>: 331, <type 'int'>: 38, <type 'instance'>: 204, <type
'RendererAgg'>: 1, <type 'float'>: 192, <type 'tkapp'>: 1, <type 'Func'>: 10}
--- 2
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 395, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 39, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 3
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 15, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 4
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 14, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 5
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 13, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 6
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 13, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 7
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 14, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 8
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 14, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
--- 9
{<type 'Func'>: 10, <type 'cell'>: 1, <type 'builtin_function_or_method'>: 12,
<type 'Point'>: 216, <type 'numpy.ndarray'>: 416, <type 'instancemethod'>: 4,
<type 'Affine'>: 75, <type 'Bbox'>: 108, <type 'set'>: 3, <type 'Interval'>:
16, <type 'tuple'>: 208, <type 'numpy.float64'>: 12, <type 'list'>: 112, <type
'dict'>: 394, <type 'str'>: 253, <class 'matplotlib.cbook.maxdict'>: 34, <type
'BinOp'>: 331, <type 'int'>: 14, <type 'RendererAgg'>: 1, <type 'function'>: 1,
<type 'instance'>: 204, <type 'float'>: 192, <type 'tkapp'>: 1}
I'm not a GUI person, but it seems suspicious to me that a tkapp is
created on every round. Maybe that's a useful clue?
--
Jouni K. Seppänen
http://www.iki.fi/jks
#!/usr/bin/env python
# NOTE: requires a debugging build of Python
import sys
import matplotlib
matplotlib.use(sys.argv[1])
from matplotlib import pylab
import gc
##############################
# Helpers for outputting the types of leaking objects
def types():
"How many objects of each type are there?"
t = dict()
for o in sys.getobjects(0):
t[type(o)] = 1+t.get(type(o), 0)
return t
def diff(t1, t2):
"Compare two outputs of types() and return the difference"
all = dict(t1)
all.update(t2)
res = dict()
for k in all.keys():
v1, v2 = t1.get(k, 0), t2.get(k, 0)
if v1 != v2:
res[k] = v2-v1
return res
prev,typ=None,None
def output():
"Output leaking objects"
global prev,typ
prev,typ = typ,types()
if prev is not None:
print diff(prev, typ)
##############################
# Investigate leaking FT2Font objects
seen = []
def investigate_fonts(i):
for o in sys.getobjects(0):
if `type(o)` == "<type 'FT2Font'>":
if id(o) in seen: continue
seen.append(id(o))
if i == 0: continue
print o, sys.getrefcount(o), len(gc.get_referrers(o))
for p in gc.get_referrers(o):
print ' ', hex(id(p)), str(p)[:90]
if type(p) == dict:
for q in gc.get_referrers(p):
print ' ', hex(id(q)), type(q)
if type(q) == dict:
print ' ', q
##############################
for i in range(10):
fig = pylab.figure()
ax = fig.add_axes([.1,.1,.8,.8])
ax.text(0,0,r'$\alpha=0$')
pylab.savefig('/tmp/foo.png')
#pylab.savefig('/tmp/foo.pdf')
pylab.close(fig)
gc.collect()
print '---', i
output()
#investigate_fonts(i)
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel