disect: track types by name string

This commit is contained in:
Michael Davidsaver
2015-01-04 12:37:43 -05:00
parent 8564630595
commit b93aee9496

View File

@ -1,14 +1,8 @@
"""Python reference counter statistics. """Python reference counter statistics.
""" """
import sys, gc, inspect, weakref, time import sys, gc, inspect, time
from UserDict import UserDict
from types import InstanceType from types import InstanceType
# a special container which we can recognize and avoid
# including in output sets, which might create reference loops
class _StatsDict(weakref.WeakKeyDictionary):
pass
class StatsDelta(object): class StatsDelta(object):
"""GC statistics tracking. """GC statistics tracking.
@ -18,10 +12,12 @@ class StatsDelta(object):
""" """
def __init__(self): def __init__(self):
self.reset() self.reset()
def reset(self): def reset(self):
"""Reset internal statistics counters """Reset internal statistics counters
""" """
self.stats, self.ntypes = None, None self.stats, self.ntypes = None, None
def collect(self, file=sys.stderr): def collect(self, file=sys.stderr):
"""Collect stats and print results to file """Collect stats and print results to file
@ -43,6 +39,13 @@ class StatsDelta(object):
first=False first=False
print >>file,' ',T,cur[T] print >>file,' ',T,cur[T]
first = True
for T in Sprev-Scur: # collected types
if first:
print >>file,'Cleaned Types'
first=False
print >>file,' ',T,-prev[T]
first = True first = True
for T in Scur&Sprev: for T in Scur&Sprev:
if cur[T]==prev[T]: if cur[T]==prev[T]:
@ -52,25 +55,33 @@ class StatsDelta(object):
first=False first=False
print >>file,' ',T,cur[T],'delta',cur[T]-prev[T] print >>file,' ',T,cur[T],'delta',cur[T]-prev[T]
else: # first call
print >>file,"All Types"
for T,C in cur.iteritems():
print >>file,' ',T,C
self.stats, self.ntypes = cur, len(cur) self.stats, self.ntypes = cur, len(cur)
#gc.collect() #gc.collect()
def gcstats(): def gcstats():
"""Count the number of instances of each type/class """Count the number of instances of each type/class
:returns: A WeakKeyDictionary mapping type to an integer number of references :returns: A dict() mapping type (as a string) to an integer number of references
""" """
all = gc.get_objects() all = gc.get_objects()
_stats = {} _stats = {}
for obj in all: for obj in all:
K = type(obj) K = type(obj)
if K in [_StatsDict, StatsDelta]: if K is StatsDelta:
continue # avoid counting ourselves continue # avoid counting ourselves
elif K is InstanceType: # instance of an old-style class elif K is InstanceType: # instance of an old-style class
K = getattr(obj, '__class__', K) K = getattr(obj, '__class__', K)
# Track types as strings to avoid holding references
K = str(K)
try: try:
_stats[K] += 1 _stats[K] += 1
except KeyError: except KeyError:
@ -81,8 +92,7 @@ def gcstats():
# This would otherwise prevent the list from being free'd # This would otherwise prevent the list from being free'd
del all del all
# use a weakref to allow types to be GC'd return _stats
return _StatsDict(_stats)
class _StatsThread(object): class _StatsThread(object):
def __init__(self, period, file): def __init__(self, period, file):