_gcdebug.py
brancholdstable
changeset 4985 02b52bf9f5f8
parent 4870 101858d845f7
child 5421 8167de96c523
equal deleted inserted replaced
4563:c25da7573ebd 4985:02b52bf9f5f8
       
     1 
       
     2 import gc, types, weakref
       
     3 
       
     4 from cubicweb.schema import CubicWebRelationSchema, CubicWebEntitySchema
       
     5 
       
     6 listiterator = type(iter([]))
       
     7 
       
     8 IGNORE_CLASSES = (
       
     9     type, tuple, dict, list, set, frozenset, type(len),
       
    10     weakref.ref, weakref.WeakKeyDictionary,
       
    11     listiterator,
       
    12     property, classmethod,
       
    13     types.ModuleType, types.FunctionType, types.MethodType,
       
    14     types.MemberDescriptorType, types.GetSetDescriptorType,
       
    15     )
       
    16 
       
    17 def _get_counted_class(obj, classes):
       
    18     for cls in classes:
       
    19         if isinstance(obj, cls):
       
    20             return cls
       
    21     raise AssertionError()
       
    22 
       
    23 def gc_info(countclasses,
       
    24             ignoreclasses=IGNORE_CLASSES,
       
    25             viewreferrersclasses=(), showobjs=False, maxlevel=1):
       
    26     gc.collect()
       
    27     gc.collect()
       
    28     counters = {}
       
    29     ocounters = {}
       
    30     for obj in gc.get_objects():
       
    31         if isinstance(obj, countclasses):
       
    32             cls = _get_counted_class(obj, countclasses)
       
    33             try:
       
    34                 counters[cls.__name__] += 1
       
    35             except KeyError:
       
    36                 counters[cls.__name__] = 1
       
    37         elif not isinstance(obj, ignoreclasses):
       
    38             try:
       
    39                 key = '%s.%s' % (obj.__class__.__module__,
       
    40                                  obj.__class__.__name__)
       
    41             except AttributeError:
       
    42                 key = str(obj)
       
    43             try:
       
    44                 ocounters[key] += 1
       
    45             except KeyError:
       
    46                 ocounters[key] = 1
       
    47         if isinstance(obj, viewreferrersclasses):
       
    48             print '   ', obj, referrers(obj, showobjs, maxlevel)
       
    49     return counters, ocounters, gc.garbage
       
    50 
       
    51 
       
    52 def referrers(obj, showobj=False, maxlevel=1):
       
    53     objreferrers = _referrers(obj, maxlevel)
       
    54     try:
       
    55         return sorted(set((type(x), showobj and x or getattr(x, '__name__', '%#x' % id(x)))
       
    56                           for x in objreferrers))
       
    57     except TypeError:
       
    58         s = set()
       
    59         unhashable = []
       
    60         for x in objreferrers:
       
    61             try:
       
    62                 s.add(x)
       
    63             except TypeError:
       
    64                 unhashable.append(x)
       
    65         return sorted(s) + unhashable
       
    66 
       
    67 def _referrers(obj, maxlevel, _seen=None, _level=0):
       
    68     interesting = []
       
    69     if _seen is None:
       
    70         _seen = set()
       
    71     for x in gc.get_referrers(obj):
       
    72         if id(x) in _seen:
       
    73             continue
       
    74         _seen.add(id(x))
       
    75         if isinstance(x, types.FrameType):
       
    76             continue
       
    77         if isinstance(x, (CubicWebRelationSchema, CubicWebEntitySchema)):
       
    78             continue
       
    79         if isinstance(x, (list, tuple, set, dict, listiterator)):
       
    80             if _level >= maxlevel:
       
    81                 pass
       
    82                 #interesting.append(x)
       
    83             else:
       
    84                 interesting += _referrers(x, maxlevel, _seen, _level+1)
       
    85         else:
       
    86             interesting.append(x)
       
    87     return interesting