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)