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

ttimerutil.py (13163B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\script\util\ttimerutil.py
      2 from __future__ import print_function
      3 import cPickle
      4 import sys
      5 import blue
      6 from carbon.common.script.util.timerstuff import ClockThis
      7 import whitelistpickle
      8 from eveprefs import prefs
      9 active = prefs.GetValue('taskletTimers', False)
     10 memActive = prefs.GetValue('taskletTimersMem', False)
     11 if not active:
     12     memActive = False
     13 if active != blue.pyos.taskletTimer.active:
     14     blue.pyos.taskletTimer.active = active
     15 if memActive != sys.getmemcontextsactive():
     16     sys.setmemcontextsactive(memActive)
     17 
     18 class Resources(object):
     19     __slots__ = ['hTime',
     20      'rTime',
     21      'kTime',
     22      'uTime',
     23      'nCalls',
     24      'nSwitches',
     25      'nBlocks',
     26      'nBytes']
     27 
     28     def __getstate__(self):
     29         return tuple([ getattr(self, slot, None) for slot in self.__slots__ ])
     30 
     31     def __setstate__(self, state):
     32         for i in range(len(self.__slots__)):
     33             setattr(self, self.__slots__[i], state[i])
     34 
     35     @staticmethod
     36     def CallgrindHeader(f):
     37         print('events: wt ut kt ct mem blk', file=f)
     38         print('event: wt: wallclock time (ns)', file=f)
     39         print('event: ut: user time (us)', file=f)
     40         print('event: kt: kernel time (us)', file=f)
     41         print('event: ct: cpu time time (us)', file=f)
     42         print('event: mem: mem allocated in context (bytes)', file=f)
     43         print('event: blk: mem allocated in context (blocks)', file=f)
     44 
     45     @staticmethod
     46     def microseconds(t):
     47         return int(t * 1000000.0 + 0.5)
     48 
     49     @staticmethod
     50     def nanoseconds(t):
     51         return int(t * 1000000000.0 + 0.5)
     52 
     53     def CallgrindPrint(self, f):
     54         print(self.nanoseconds(self.hTime), self.microseconds(self.uTime), self.microseconds(self.kTime), end=' ', file=f)
     55         print(self.microseconds(self.uTime + self.kTime), end=' ', file=f)
     56         print(self.nBytes, self.nBlocks, file=f)
     57 
     58     modes = ['wallclock',
     59      'kerneltime',
     60      'usertime',
     61      'cputime',
     62      'real',
     63      'membytes',
     64      'memblocks',
     65      'nocputime']
     66     types = ['s',
     67      's',
     68      's',
     69      's',
     70      's',
     71      'b',
     72      '',
     73      's']
     74     mode = 0
     75 
     76     def GetModes(self):
     77         return self.modes
     78 
     79     GetModes = classmethod(GetModes)
     80 
     81     def SetMode(self, m = 'wallclock'):
     82         if m:
     83             self.mode = self.modes.index(m)
     84         else:
     85             self.mode = 0
     86 
     87     SetMode = classmethod(SetMode)
     88 
     89     def GetMode(self):
     90         return (self.modes[self.mode], self.types[self.mode])
     91 
     92     GetMode = classmethod(GetMode)
     93 
     94     def GetVal(self):
     95         m = self.mode
     96         if m == 0:
     97             return self.hTime
     98         if m == 1:
     99             return self.kTime
    100         if m == 2:
    101             return self.uTime
    102         if m == 3:
    103             return self.kTime + self.uTime
    104         if m == 4:
    105             return self.rTime
    106         if m == 5:
    107             return self.nBytes
    108         if m == 6:
    109             return self.nBlocks
    110         if m == 7:
    111             return self.hTime - self.kTime - self.uTime
    112         raise ValueError
    113 
    114     def GetType(self):
    115         return self.types[self.mode]
    116 
    117     def __init__(self, o = None):
    118         for i in self.__slots__:
    119             setattr(self, i, 0)
    120 
    121         if type(o) is dict:
    122             for k, v in o.items():
    123                 if k in self.__slots__:
    124                     setattr(self, k, v)
    125 
    126         elif type(o) is Resources:
    127             for k in self.__slots__:
    128                 setattr(self, k, getattr(o, k))
    129 
    130     def copy(self):
    131         r = Resources()
    132         for n in self.__slots__:
    133             setattr(r, n, getattr(self, n))
    134 
    135         return r
    136 
    137     def IMax(self, o):
    138         for k in self.__slots__:
    139             setattr(self, k, max(getattr(self, k), getattr(o, k)))
    140 
    141     def __iadd__(self, o):
    142         r = self.rTime
    143         for k in self.__slots__:
    144             setattr(self, k, getattr(self, k) + getattr(o, k))
    145 
    146         self.rTime = max(r, o.rTime)
    147         return self
    148 
    149     def __add__(self, o):
    150         r = Resources(self)
    151         r += o
    152         return r
    153 
    154 
    155 class Timer(object):
    156     __slots__ = ['name',
    157      'key',
    158      'own',
    159      'cum',
    160      'callees',
    161      'callers']
    162 
    163     def __init__(self, name = 'unset'):
    164         self.name = self.key = name
    165         self.own = Resources()
    166         self.cum = Resources()
    167         self.callees = {}
    168         self.callers = {}
    169 
    170     def __getstate__(self):
    171         return tuple([ getattr(self, slot, None) for slot in self.__slots__ ])
    172 
    173     def __setstate__(self, state):
    174         for i in range(len(self.__slots__)):
    175             setattr(self, self.__slots__[i], state[i])
    176 
    177     def copy(self):
    178         t = Timer(self.name)
    179         t.own = self.own.copy()
    180         t.cum = self.cum.copy()
    181         t.callees = self.callees.copy()
    182         t.callers = self.callers.copy()
    183         t.key = self.key
    184         return t
    185 
    186     def GetTime(self):
    187         return self.own.GetVal()
    188 
    189     def GetCTime(self):
    190         return self.cum.GetVal()
    191 
    192     def GetType(self):
    193         return self.cum.GetType()
    194 
    195     time = property(GetTime)
    196     ctime = property(GetCTime)
    197 
    198     def GetSwitches(self):
    199         return self.own.nSwitches
    200 
    201     switches = property(GetSwitches)
    202 
    203     def GetCalls(self):
    204         return self.own.nCalls
    205 
    206     calls = property(GetCalls)
    207 
    208     def __iadd__(self, other):
    209         self.own += other.own
    210         self.cum.IMax(other.cum)
    211         self.callees = self.callers = {}
    212         return self
    213 
    214     def __add__(self, other):
    215         r = self.copy()
    216         r += other
    217         return r
    218 
    219     def __le__(self, other):
    220         return self.key <= other.key
    221 
    222 
    223 class Callee(object):
    224     __slots__ = ['ncalls', 'cum']
    225 
    226     def __init__(self, nc, c):
    227         self.ncalls, self.cum = nc, c
    228 
    229     def __getstate__(self):
    230         return tuple([ getattr(self, slot, None) for slot in self.__slots__ ])
    231 
    232     def __setstate__(self, state):
    233         for i in range(len(self.__slots__)):
    234             setattr(self, self.__slots__[i], state[i])
    235 
    236     def GetCTime(self):
    237         return self.cum.GetVal()
    238 
    239     def GetType(self):
    240         return self.cum.GetType()
    241 
    242     ctime = property(GetCTime)
    243     type = property(GetType)
    244 
    245     def __iadd__(self, other):
    246         self.ncalls += other.ncalls
    247         self.cum += other.cum
    248         return self
    249 
    250 
    251 def GetChains(filter = None, root = True):
    252     import sys
    253     if hasattr(sys, 'getmemcontexts'):
    254         taskletmem = sys.getmemcontexts()
    255     else:
    256         taskletmem = {}
    257     chains = []
    258     done = {}
    259     threadTimes = blue.pyos.taskletTimer.GetThreadTimes()
    260     processTimes = blue.pyos.taskletTimer.GetProcessTimes()
    261     tasklets = blue.pyos.taskletTimer.GetTasklets()
    262     for chain in tasklets:
    263         r = []
    264         truncate = False
    265         for i in chain[::-1]:
    266             id = i['Id']
    267             key = i['Key']
    268             if id not in done:
    269                 res = Resources(i)
    270                 if id in taskletmem:
    271                     res.nBytes, res.nBlocks = taskletmem[id]
    272                     del taskletmem[id]
    273                 done[id] = res
    274             res = done[id]
    275             r.append((id, key, res))
    276             if truncate:
    277                 break
    278             if filter and filter == key:
    279                 truncate = True
    280 
    281         chains.append(r[::-1])
    282 
    283     if root:
    284         res = Resources()
    285         app = [(-2, 'root', res)]
    286         chains = [ app + chain for chain in chains ]
    287     if taskletmem and not filter:
    288         for key, val in taskletmem.iteritems():
    289             other = Resources()
    290             other.nBytes, other.nBlocks = val
    291             chains.append([(key, '[orphaned mem ctxt]::%d' % key, other)])
    292 
    293     return (chains, threadTimes, processTimes)
    294 
    295 
    296 def TimersFromChains(chains, filter = None):
    297     timers = {}
    298     added = {}
    299     for chain in chains:
    300         blue.pyos.BeNice()
    301         rec = {}
    302         for i in chain:
    303             key = i[1]
    304             rec[key] = rec.get(key, 0) + 1
    305 
    306         if chain and chain[0][0] == -2:
    307             rec[chain[0][1]] += 1
    308         cum = Resources()
    309         lastKey = None
    310         found = filter == None
    311         for i in reversed(chain):
    312             id = i[0]
    313             key = i[1]
    314             own = i[2]
    315             if key not in timers:
    316                 timers[key] = Timer(key)
    317             timer = timers[key]
    318             if id not in added:
    319                 timer.own += own
    320                 cum += own
    321                 added[id] = True
    322             if rec[key] == 1:
    323                 timer.cum += cum
    324             else:
    325                 rec[key] -= 1
    326             if filter and not found:
    327                 found = filter == key
    328             if lastKey and found:
    329                 if lastKey in timer.callees:
    330                     timer.callees[lastKey] += callee
    331                 else:
    332                     timer.callees[lastKey] = callee
    333             lastKey = key
    334             callee = Callee(own.nCalls, cum.copy())
    335 
    336     for caller, timer in timers.iteritems():
    337         for callee, val in timer.callees.iteritems():
    338             timers[callee].callers[caller] = val
    339 
    340     return timers
    341 
    342 
    343 def GetTimer(key):
    344     timers = TimersFromChains(GetChains()[0])
    345     return timers.get(key, None)
    346 
    347 
    348 taskletWhiteList = []
    349 
    350 def InitTaskletWhiteList():
    351     global taskletWhiteList
    352     taskletWhiteList = []
    353     import copy_reg
    354     taskletWhiteList.append(copy_reg._reconstructor)
    355     taskletWhiteList.append(Callee)
    356     taskletWhiteList.append(Resources)
    357     taskletWhiteList.append(TaskletSnapshot)
    358     taskletWhiteList.append(Timer)
    359     import __builtin__
    360     taskletWhiteList.append(__builtin__.dict)
    361     taskletWhiteList.append(__builtin__.object)
    362 
    363 
    364 def _getTaskletWhitelist():
    365     return taskletWhiteList
    366 
    367 
    368 def find_global(moduleName, className):
    369     return whitelistpickle.find_global(moduleName, className, _getTaskletWhitelist)
    370 
    371 
    372 def Unpickler(file):
    373     if not taskletWhiteList:
    374         InitTaskletWhiteList()
    375     u = whitelistpickle.cPickleUnpickler(file)
    376     u.find_global = find_global
    377     return u
    378 
    379 
    380 def LoadPickle(fileObj):
    381     return Unpickler(fileObj).load()
    382 
    383 
    384 class TaskletSnapshot(dict):
    385 
    386     def __init__(self):
    387         chains, self.threadTimes, self.processTimes = ClockThis('TaskletSnapshot::GetChains', GetChains)
    388         timers = ClockThis('TaskletSnapshot::TimersFromChains', TimersFromChains, chains)
    389         self.update(timers)
    390 
    391     def Save(self, filename = None):
    392         if filename:
    393             file = open(filename, 'wb')
    394             try:
    395                 cPickle.dump(self, file)
    396             finally:
    397                 file.close()
    398 
    399         else:
    400             return cPickle.dumps(self)
    401 
    402     def Load(filename):
    403         file = open(filename, 'rb')
    404         try:
    405             r = LoadPickle(file)
    406         finally:
    407             file.close()
    408 
    409         return r
    410 
    411     Load = staticmethod(Load)
    412 
    413     def PrintCallgrindData(self, f):
    414         print('creator: blue tasklet timers', file=f)
    415         Resources.CallgrindHeader(f)
    416 
    417         def splitname(n):
    418             idx = n.rfind('::')
    419             if idx >= 0:
    420                 fn = n
    421                 fl = n[:idx]
    422                 if not fl:
    423                     fl = '<none>'
    424                 if not fn:
    425                     fn = '<none>'
    426                 return (fl.replace(' ', '_'), fn.replace(' ', '_'))
    427             return ('<none>', n.replace(' ', '_'))
    428 
    429         mfn, mfl = {}, {}
    430         ifn = ifl = 1
    431         for k, v in self.iteritems():
    432             fl, fn = splitname(v.name.encode('utf_8'))
    433             if fl not in mfl:
    434                 mfl[fl] = '(%d)' % ifl
    435                 ifl += 1
    436             if fn not in mfn:
    437                 mfn[fn] = '(%d)' % ifn
    438                 ifn += 1
    439 
    440         print('#function mapping', file=f)
    441         for k, v in mfn.iteritems():
    442             print('fn=%s %s' % (v, k), file=f)
    443 
    444         print('#filename mapping', file=f)
    445         for k, v in mfl.iteritems():
    446             print('fl=%s %s' % (v, k), file=f)
    447 
    448         if False:
    449             for k in mfl.keys():
    450                 mfl[k] = k
    451 
    452             for k in mfn.keys():
    453                 mfn[k] = k
    454 
    455         print('\n# call stats', file=f)
    456         lastfn = lastfl = None
    457         for timer in self.itervalues():
    458             print(file=f)
    459             fl, fn = splitname(timer.name.encode('utf_8'))
    460             if fl != lastfl:
    461                 print('fl=%s' % mfl[fl], file=f)
    462                 lastfl = fl
    463             if fn != lastfn:
    464                 print('fn=%s' % mfn[fn], file=f)
    465                 lastfn = fn
    466             print(0, end=' ', file=f)
    467             timer.own.CallgrindPrint(f)
    468             for key, callee in timer.callees.iteritems():
    469                 target = self[key]
    470                 cfl, cfn = splitname(target.name.encode('utf_8'))
    471                 if cfl != fl:
    472                     print('cfl=%s' % mfl[cfl], file=f)
    473                 if cfn != fn:
    474                     print('cfn=%s' % mfn[cfn], file=f)
    475                 print('calls=%d, 0' % callee.ncalls, file=f)
    476                 print(0, end=' ', file=f)
    477                 callee.cum.CallgrindPrint(f)
    478 
    479         print('#end', file=f)
    480 
    481 
    482 def SetTimeMode(*args, **kwargs):
    483     return Resources.SetMode(*args, **kwargs)
    484 
    485 
    486 def GetTimeMode(*args, **kwargs):
    487     return Resources.GetMode(*args, **kwargs)
    488 
    489 
    490 def GetTimeModes(*args, **kwargs):
    491     return Resources.GetModes(*args, **kwargs)