[pypy-svn] r15696 - pypy/dist/pypy/translator/tool
arigo at codespeak.net
arigo at codespeak.net
Fri Aug 5 17:10:27 CEST 2005
Author: arigo
Date: Fri Aug 5 17:10:25 2005
New Revision: 15696
Added:
pypy/dist/pypy/translator/tool/reftracker.py (contents, props changed)
Log:
A useful tool: a general-purpose reference tracker, to look for why objects
are unexpectedly kept alive in Python programs.
(dot+pygame tool)
Added: pypy/dist/pypy/translator/tool/reftracker.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/tool/reftracker.py Fri Aug 5 17:10:25 2005
@@ -0,0 +1,105 @@
+"""
+General-purpose reference tracker.
+Usage: call track(obj).
+"""
+
+import autopath
+import gc
+from pypy.translator.tool.graphpage import GraphPage, DotGen
+
+
+MARKER = object()
+
+
+class RefTrackerPage(GraphPage):
+
+ def compute(self, objectlist):
+ assert objectlist[0] is MARKER
+ self.objectlist = objectlist
+ dotgen = DotGen('reftracker')
+ id2typename = {}
+ nodes = {}
+ edges = {}
+
+ def addedge(o1, o2):
+ key = (id(o1), id(o2))
+ slst = []
+ if type(o1) in (list, tuple):
+ for i in range(len(o1)):
+ if o1[i] is o2:
+ slst.append('[%d]' % i)
+ elif type(o1) is dict:
+ for k, v in o1.items():
+ if v is o2:
+ slst.append('[%r]' % (k,))
+ edges[key] = ', '.join(slst)
+
+ for i in range(1, len(objectlist)):
+ s = repr(objectlist[i])
+ word = '0x%x' % id(objectlist[i])
+ if len(s) > 50:
+ self.links[word] = s
+ s = s[:20] + ' ... ' + s[-20:]
+ s = '<%s> %s\\n%s' % (type(objectlist[i]).__name__,
+ word,
+ s)
+ nodename = 'node%d' % len(nodes)
+ dotgen.emit_node(nodename, label=s, shape="box")
+ nodes[id(objectlist[i])] = nodename
+ for o2 in gc.get_referents(objectlist[i]):
+ if o2 is None:
+ continue
+ addedge(objectlist[i], o2)
+ id2typename[id(o2)] = type(o2).__name__
+ del o2
+ for o2 in gc.get_referrers(objectlist[i]):
+ if o2 is None:
+ continue
+ if type(o2) is list and o2 and o2[0] is MARKER:
+ continue
+ addedge(o2, objectlist[i])
+ id2typename[id(o2)] = type(o2).__name__
+ del o2
+
+ for ids, label in edges.items():
+ for id1 in ids:
+ if id1 not in nodes:
+ nodename = 'node%d' % len(nodes)
+ word = '0x%x' % id1
+ s = '<%s> %s' % (id2typename[id1], word)
+ dotgen.emit_node(nodename, label=s)
+ nodes[id1] = nodename
+ self.links[word] = s
+ id1, id2 = ids
+ dotgen.emit_edge(nodes[id1], nodes[id2], label=label)
+
+ self.source = dotgen.generate(target=None)
+
+ def followlink(self, word):
+ id1 = int(word, 16)
+ found = None
+ objectlist = self.objectlist
+ for i in range(1, len(objectlist)):
+ for o2 in gc.get_referents(objectlist[i]):
+ if id(o2) == id1:
+ found = o2
+ for o2 in gc.get_referrers(objectlist[i]):
+ if id(o2) == id1:
+ found = o2
+ if found is not None:
+ objectlist = objectlist + [found]
+ else:
+ print '*** NOTE: object not found'
+ return RefTrackerPage(objectlist)
+
+
+def track(o):
+ """Invoke a dot+pygame object reference tracker."""
+ page = RefTrackerPage([MARKER, o])
+ del o
+ page.display()
+
+
+if __name__ == '__main__':
+ d = {"lskjadldjslkj": "adjoiadoixmdoiemdwoi"}
+ track(d)
More information about the Pypy-commit
mailing list