NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

traceref.py (11467B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\util\traceref.py
      2 from __future__ import print_function
      3 from __future__ import absolute_import
      4 import gc
      5 from . import inspect
      6 import sys
      7 import types
      8 import stackless
      9 import blue
     10 
     11 def ObjectHistogram(deltaFrom = {}):
     12     hist = {}
     13     for obj in gc.get_objects():
     14         try:
     15             objType = ClassOrType(obj)
     16         except ReferenceError:
     17             continue
     18 
     19         hist[objType] = hist.get(objType, 0) + 1
     20 
     21     for objType in set(hist).union(deltaFrom):
     22         hist[objType] = hist.get(objType, 0) - deltaFrom.get(objType, 0)
     23 
     24     report = _SortList([ (count, (objType, count)) for objType, count in hist.iteritems() ])
     25     report.reverse()
     26     print('Histogram BEGIN -----------------------------------')
     27     if deltaFrom:
     28         print('(Delta from previous.)')
     29     print('%s%20s' % ('Type', 'Count'))
     30     for objType, count in report:
     31         if count != 0:
     32             print('%s%20s' % (objType, count))
     33 
     34     print('Histogram END -------------------------------------')
     35     return hist
     36 
     37 
     38 def GetLiveObjectsByTypeName(typeName):
     39     ret = []
     40     for obj in gc.get_objects():
     41         try:
     42             if typeName in ClassOrType(obj).__name__:
     43                 ret.append(obj)
     44         except ReferenceError:
     45             pass
     46 
     47     return ret
     48 
     49 
     50 def GetLiveObjectsByType(type_):
     51     return [ obj for obj in gc.get_objects() if isinstance(obj, type_) ]
     52 
     53 
     54 def _RawRefGraph(ob, ignore = (), depthLimit = None, breadthLimit = None):
     55 
     56     def Ignore(*obs):
     57         for ob in obs:
     58             ignored.add(id(ob))
     59 
     60     def IgnoreFrame(f):
     61         Ignore(f, f.f_locals)
     62 
     63     def IgnoreCallStack():
     64         f = inspect.currentframe()
     65         while f is not None:
     66             IgnoreFrame(f)
     67             f = f.f_back
     68 
     69     def Graph(ob, depth = 0):
     70         blue.pyos.BeNice()
     71         if depthLimit is not None and depth > depthLimit:
     72             return
     73         IgnoreCallStack()
     74         ret[id(ob)] = rfrs = []
     75         l = gc.get_referrers(ob)
     76         Ignore(rfrs, l)
     77         breadth = 0
     78         for rfr in l:
     79             if id(rfr) not in ignored:
     80                 breadth += 1
     81                 if breadthLimit is not None and breadth > breadthLimit:
     82                     return
     83                 rfrs.append(rfr)
     84                 if id(rfr) not in ret:
     85                     for type_ in [stackless.module,
     86                      stackless.modict,
     87                      stackless.frame,
     88                      stackless.function,
     89                      stackless.listiterator]:
     90                         if isinstance(rfr, type_):
     91                             break
     92                     else:
     93                         Graph(rfr, depth + 1)
     94 
     95     ret = {}
     96     ignored = set()
     97     Ignore(ret, ignored, sys.modules['__main__'].__dict__, *ignore)
     98     IgnoreFrame(inspect.currentframe())
     99     Graph(ob)
    100     return ret
    101 
    102 
    103 def TestRawRefGraph():
    104 
    105     class A:
    106         pass
    107 
    108     o = A()
    109     d = {'a si': a}
    110     a.dd = d
    111     import pprint
    112     pprint.pprint(_RawRefGraph(a))
    113 
    114 
    115 def TestAnnotatedRefGraph(verbose = False):
    116 
    117     def ImportHack(name):
    118         return sys.modules.setdefault(name, types.ModuleType(name))
    119 
    120     foo = ImportHack('foo')
    121     bar = ImportHack('bar')
    122 
    123     class Blah:
    124         pass
    125 
    126     o = Blah()
    127     foo.o = o
    128     foo.alias = o
    129     o.self = o
    130     p = bar.p = Blah()
    131     p.oo = p.oOo = o
    132     l = foo.l = [o, 'blah', o]
    133     t = foo.t = (o, 'bleh', o)
    134     d = bar.d = {'o si': o,
    135      'o si also': o}
    136     q = Blah()
    137     q.o = o
    138     m = [o]
    139     u = (o,)
    140     e = {'o': o}
    141     die = False
    142 
    143     def f():
    144         b = o
    145         while not die:
    146             blue.pyos.synchro.SleepWallclock(0)
    147 
    148     import uthread
    149     uthread.new(f)
    150     blue.pyos.synchro.SleepWallclock(0)
    151     try:
    152         PrintRefPaths(o, verbose=verbose)
    153     finally:
    154         die = True
    155 
    156 
    157 def PrintRefPaths(obj, ignore = (), verbose = False, depthLimit = None, breadthLimit = None):
    158 
    159     class loop:
    160         pass
    161 
    162     def PathsFromRef(ref, prevPath = []):
    163         newPath = prevPath + [ref]
    164         if ref.refs:
    165             ret = []
    166             for ref in ref.refs:
    167                 blue.pyos.BeNice()
    168                 if ref in newPath:
    169                     ret.append([ref, loop])
    170                 else:
    171                     for path in PathsFromRef(ref, newPath):
    172                         ret.append([ref] + path)
    173 
    174             return ret
    175         else:
    176             return [[]]
    177 
    178     def PathStr(path):
    179         rev = path
    180         rev.reverse()
    181         if rev[0] is loop:
    182             prefix = ['(CYCLE)']
    183             rev = rev[1:]
    184         else:
    185             root = rev[0].obj
    186             if isinstance(root, stackless.frame) or isinstance(root, stackless.function):
    187                 prefix = []
    188             elif isinstance(root, stackless.module):
    189                 prefix = [root.__name__]
    190             elif isinstance(root, stackless.modict):
    191                 prefix = [root.__module__]
    192             else:
    193                 prefix = ['<%s at %x>' % (ClassOrType(root).__name__, id(root))]
    194         if verbose:
    195 
    196             def fn(ref):
    197                 if ClassOrType(ref.obj) in (list,
    198                  tuple,
    199                  dict,
    200                  stackless.frame):
    201                     return ref.expr()
    202                 else:
    203                     typeName = getattr(ref.obj, '__guid__', ClassOrType(ref.obj).__name__)
    204                     return '(%s)%s' % (typeName, ref.expr())
    205 
    206         else:
    207             fn = lambda ref: ref.expr()
    208         return ''.join(prefix + [ fn(each) for each in rev ])
    209 
    210     refs = _AnnotatedRefGraph(obj, ignore, depthLimit, breadthLimit)
    211     allPaths = []
    212     for ref in refs:
    213         allPaths.extend([ [ref] + path for path in PathsFromRef(ref) ])
    214 
    215     pathStrs = map(PathStr, allPaths)
    216     pathStrs.sort()
    217     print('Paths are (in alphabetical order):')
    218     for each in pathStrs:
    219         print('   ', each)
    220 
    221     del allPaths[:]
    222     allPurged = set()
    223 
    224     def PurgeRef(ref):
    225         if id(ref) in allPurged:
    226             return
    227         allPurged.add(id(ref))
    228         map(PurgeRef, ref.refs)
    229         del ref.refs[:]
    230 
    231     map(PurgeRef, refs)
    232 
    233 
    234 def _AnnotatedRefGraph(obj, ignore = (), depthLimit = None, breadthLimit = None):
    235     handledAnnotations = {}
    236     handledIndices = set()
    237 
    238     def IndexHandled(obID, refID, categ, index):
    239         ret = (obID,
    240          refID,
    241          categ,
    242          index) in handledIndices
    243         handledIndices.add((obID,
    244          refID,
    245          categ,
    246          index))
    247         handledIndices.add((obID,
    248          refID,
    249          'unknown',
    250          None))
    251         return ret
    252 
    253     class Ref:
    254 
    255         def __init__(self, obj, categ, index):
    256             self.obj = obj
    257             self.categ = categ
    258             self.index = index
    259             self.refs = handledAnnotations[id(obj)]
    260 
    261         def __str__(self):
    262             return 'Ref(%s, %s, <%s at %x>)' % (self.categ,
    263              self.index,
    264              ClassOrType(self.obj).__name__,
    265              id(self.obj))
    266 
    267         def expr(self):
    268             if self.categ == 'frame_local':
    269                 return "<local '%s' at %s:%s(%s)>" % (self.index,
    270                  self.obj.f_code.co_filename,
    271                  self.obj.f_code.co_firstlineno,
    272                  self.obj.f_code.co_name)
    273             elif self.categ == 'func_closure':
    274                 return '<closed over at %s:%s(%s)>' % (self.obj.__code__.co_filename, self.obj.__code__.co_firstlineno, self.obj.__name__)
    275             elif self.categ == 'attr':
    276                 return '.%s' % self.index
    277             elif self.categ in ('seq', 'dict'):
    278                 return '[%r]' % self.index
    279             else:
    280                 return '<%s>' % self
    281 
    282     handledAnnotations[id(None)] = []
    283     omitted = Ref(None, 'omitted', None)
    284 
    285     def FrameDetails(obj, rfr):
    286         if not isinstance(rfr, stackless.frame):
    287             return None
    288         for name, val in rfr.f_locals.iteritems():
    289             if val is obj and not IndexHandled(id(obj), id(rfr), 'frame_local', name):
    290                 return (rfr, 'frame_local', name)
    291 
    292     def FuncDetails(obj, rfr):
    293         for rfrfr in GetRefs(rfr):
    294             if isinstance(rfrfr, stackless.function):
    295                 for name, val in rfrfr.__dict__.iteritems():
    296                     if val is obj and not IndexHandled(id(obj), id(rfrfr), 'func_dict', name):
    297                         return (rfrfr, 'func_dict', i)
    298 
    299             elif isinstance(rfr, stackless.cell):
    300                 for rfrfrfr in GetRefs(rfrfr):
    301                     if isinstance(rfrfrfr, stackless.function):
    302                         for i, cell in enumerate(rfrfrfr.__closure__ or ()):
    303                             if cell is rfr and not IndexHandled(id(obj), id(rfrfrfr), 'func_closure', i):
    304                                 IndexHandled(id(obj), id(rfr), 'seq', i)
    305                                 return (rfrfrfr, 'func_closure', i)
    306 
    307     def AttrDetails(obj, rfr):
    308         if isinstance(rfr, stackless.modict):
    309             ret = DictDetails(obj, rfr)
    310             if ret is not None:
    311                 rfr, categ, index = ret
    312                 return (rfr, 'attr', index)
    313         for rfrfr in GetRefs(rfr):
    314             for name in dir(rfrfr):
    315                 try:
    316                     if getattr(rfrfr, name, None) is obj and not IndexHandled(id(obj), id(rfr), 'dict', name):
    317                         return (rfrfr, 'attr', name)
    318                 except TypeError:
    319                     sys.exc_clear()
    320 
    321     def DictDetails(obj, rfr):
    322         if not hasattr(rfr, 'iteritems'):
    323             return None
    324         for key, val in rfr.iteritems():
    325             if val is obj and not IndexHandled(id(obj), id(rfr), 'dict', key):
    326                 return (rfr, 'dict', key)
    327 
    328     def SequenceDetails(obj, rfr):
    329         try:
    330             for i, val in enumerate(rfr):
    331                 if val is obj and not IndexHandled(id(obj), id(rfr), 'seq', i):
    332                     return (rfr, 'seq', i)
    333 
    334         except TypeError:
    335             try:
    336                 enumerate(rfr)
    337             except TypeError:
    338                 sys.exc_clear()
    339                 return None
    340 
    341             raise
    342 
    343     def UnknownDetails(obj, rfr):
    344         if not IndexHandled(id(obj), id(rfr), 'unknown', None):
    345             return (rfr, 'unknown', None)
    346 
    347     def NextAnnotation(obj, rfr):
    348         for func in [FrameDetails,
    349          FuncDetails,
    350          AttrDetails,
    351          DictDetails,
    352          SequenceDetails,
    353          UnknownDetails]:
    354             ref = func(obj, rfr)
    355             if ref is not None:
    356                 return ref
    357 
    358     def AnnotateRefs(obj):
    359         ret = []
    360         handledAnnotations[id(obj)] = []
    361         for rfr in GetRefs(obj):
    362             while True:
    363                 next = NextAnnotation(obj, rfr)
    364                 if next is None:
    365                     break
    366                 ostensibleRfr, categ, index = next
    367                 if id(ostensibleRfr) not in handledAnnotations:
    368                     AnnotateRefs(ostensibleRfr)
    369                 ret.append(Ref(ostensibleRfr, categ, index))
    370 
    371         handledAnnotations[id(obj)].extend(ret)
    372         return ret
    373 
    374     raw = _RawRefGraph(obj, ignore, depthLimit, breadthLimit)
    375 
    376     def GetRefs(obj):
    377         return raw.get(id(obj), [])
    378 
    379     try:
    380         return AnnotateRefs(obj)
    381     finally:
    382         raw.clear()
    383 
    384 
    385 def ClassOrType(obj):
    386     return getattr(obj, '__class__', type(obj))
    387 
    388 
    389 def _SortList(lst):
    390     lst.sort()
    391     return [ item[1] for item in lst ]
    392 
    393 
    394 import carbon.common.script.util.autoexport as autoexport
    395 exports = autoexport.AutoExports('util', locals())