__init__.py (15082B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\bluepy\__init__.py 2 from future.utils import raise_ 3 import atexit 4 import blue 5 import contextlib 6 import re 7 import stackless 8 import sys 9 import traceback 10 import weakref 11 import utillib as util 12 import ccpProfile 13 import datetime 14 STACKLESS_TRACING_ENABLED_KEY = 'stackless_tracing_enabled' 15 tasklet_id = 0 16 17 class TaskletExt(stackless.tasklet): 18 __slots__ = ['context', 19 'localStorage', 20 'storedContext', 21 'startTime', 22 'endTime', 23 'runTime', 24 'tasklet_id', 25 'origin_traceback', 26 'highlighted', 27 'method_name', 28 'module_name', 29 'file_name', 30 'line_number', 31 'parent_callsite', 32 'tracer', 33 'trace_id', 34 'parent_id', 35 'sampled', 36 'ingress_id', 37 'sample_rate', 38 'creation_datetime'] 39 40 @staticmethod 41 def GetWrapper(method): 42 if not callable(method): 43 raise TypeError('TaskletExt::__new__ argument "method" must be callable.') 44 45 def CallWrapper(*args, **kwds): 46 current = stackless.getcurrent() 47 current.startTime = blue.os.GetWallclockTimeNow() 48 oldtimer = PushTimer(current.context) 49 exc = None 50 with tasklet_trace(current): 51 try: 52 try: 53 return method(*args, **kwds) 54 except TaskletExit as e: 55 pass 56 except SystemExit as e: 57 import logmodule as log 58 log.general.Log('system %s exiting with %r' % (stackless.getcurrent(), e), log.LGINFO) 59 except Exception: 60 import logmodule as log 61 log.LogException('Unhandled exception in %r' % stackless.getcurrent()) 62 63 return 64 except: 65 traceback.print_exc() 66 if exc: 67 traceback.print_exception(exc[0], exc[1], exc[2]) 68 finally: 69 exc = None 70 PopTimer(oldtimer) 71 current.endTime = blue.os.GetWallclockTimeNow() 72 73 return CallWrapper 74 75 def __new__(cls, ctx, method = None, stackless_tracing_enabled = True): 76 global tasklet_id 77 tid = tasklet_id 78 tasklet_id += 1 79 if method: 80 t = stackless.tasklet.__new__(cls, cls.GetWrapper(method)) 81 else: 82 t = stackless.tasklet.__new__(cls) 83 t.creation_datetime = datetime.datetime.utcnow() 84 c = stackless.getcurrent() 85 ls = getattr(c, 'localStorage', None) 86 if ls is None: 87 t.localStorage = {} 88 else: 89 t.localStorage = dict(ls) 90 t.storedContext = t.context = ctx 91 t.method_name = getattr(method, '__name__', 'unknown_method') 92 t.module_name = getattr(method, '__module__', 'unknown_module') 93 try: 94 t.file_name = method.__code__.co_filename 95 t.line_number = method.__code__.co_firstlineno 96 except AttributeError: 97 t.file_name = 'unknown_file' 98 t.line_number = 0 99 100 parent_module_name = getattr(c, 'module_name', 'unknown_parent_module') 101 parent_method_name = getattr(c, 'method_name', 'unknown_parent_method') 102 t.parent_callsite = ('{}.{}'.format(parent_module_name, parent_method_name),) 103 if stackless_tracing_enabled: 104 cls.copy_tracer_and_state(c, t) 105 t.runTime = 0.0 106 t.tasklet_id = tid 107 t.highlighted = False 108 tasklets[t] = True 109 return t 110 111 @staticmethod 112 def copy_tracer_and_state(old, new): 113 trace_context_slots = ['trace_id', 114 'parent_id', 115 'sampled', 116 'ingress_id', 117 'sample_rate'] 118 for trace_slot in trace_context_slots: 119 setattr(new, trace_slot, getattr(old, trace_slot, None)) 120 121 tracer = getattr(old, 'tracer', None) 122 if tracer is not None: 123 setattr(new, 'tracer', tracer.clone()) 124 125 def bind(self, callableObject): 126 return stackless.tasklet.bind(self, self.CallWrapper(callableObject)) 127 128 def __repr__(self): 129 abps = [ getattr(self, attr) for attr in ['alive', 130 'blocked', 131 'paused', 132 'scheduled'] ] 133 abps = ''.join((str(int(flag)) for flag in abps)) 134 return '<TaskletExt object at 0x%x, abps=%s, ctxt=%r>' % (id(self), abps, getattr(self, 'storedContext', None)) 135 136 def __reduce__(self): 137 return (str, ("__reduce__()'d " + repr(self),)) 138 139 def PushTimer(self, ctxt): 140 blue.pyos.taskletTimer.EnterTasklet(ctxt) 141 142 def PopTimer(self, ctxt): 143 blue.pyos.taskletTimer.ReturnFromTasklet(ctxt) 144 145 def GetCurrent(self): 146 blue.pyos.taskletTimer.GetCurrent() 147 148 def GetWallclockTime(self): 149 return (blue.os.GetWallclockTimeNow() - self.startTime) * 1e-07 150 151 def GetRunTime(self): 152 return self.runTime + blue.pyos.GetTimeSinceSwitch() 153 154 155 tasklets = weakref.WeakKeyDictionary() 156 ctxtfilter = re.compile('at 0x[0-9A-F]+') 157 158 def tasklet_trace(t): 159 tracer = getattr(t, 'tracer', None) 160 if tracer is None: 161 return no_tasklet_tracer() 162 return tracer.get_tasklet_tracer(t) 163 164 165 @contextlib.contextmanager 166 def no_tasklet_tracer(): 167 yield 168 169 170 def tracing_enabled(**kwargs): 171 if STACKLESS_TRACING_ENABLED_KEY not in kwargs.keys(): 172 return (True, kwargs) 173 stackless_tracing_enabled = kwargs[STACKLESS_TRACING_ENABLED_KEY] 174 del kwargs[STACKLESS_TRACING_ENABLED_KEY] 175 return (stackless_tracing_enabled, kwargs) 176 177 178 def CreateTaskletExt(func, *args, **kw): 179 ctx = ctxtfilter.sub('', repr(func)) 180 ctx = blue.pyos.taskletTimer.GetCurrent().split('^')[-1] + '^' + ctx 181 stackless_tracing_enabled, kw = tracing_enabled(**kw) 182 t = TaskletExt(ctx, func, stackless_tracing_enabled=stackless_tracing_enabled) 183 t(*args, **kw) 184 return t 185 186 187 def Shutdown(exitprocs): 188 189 def RunAll(): 190 stackless.getcurrent().block_trap = True 191 for proc in exitprocs: 192 try: 193 proc() 194 except Exception: 195 import logmodule as log 196 log.LogException('exitproc ' + repr(proc), toAlertSvc=False) 197 sys.exc_clear() 198 199 if exitprocs: 200 TaskletExt('Shutdown', RunAll)() 201 intr = stackless.run(1000000) 202 if intr: 203 log.general.Log('ExitProcs interrupted at tasklet ' + repr(intr), log.LGERR) 204 GetTaskletDump(True) 205 if len(tasklets): 206 KillTasklets() 207 GetTaskletDump(True) 208 209 210 def GetTaskletDump(logIt = True): 211 import logmodule as log 212 lines = [] 213 lines.append('GetTaskletDump: %s TaskletExt objects alive' % len(tasklets)) 214 lines.append('[context] - [code] - [stack depth] - [creation context]') 215 for t in tasklets.keys(): 216 try: 217 if t.frame: 218 stack = traceback.extract_stack(t.frame, 1) 219 depth = len(stack) 220 f = stack[-1] 221 code = '%s(%s)' % (f[0], f[1]) 222 else: 223 code, depth = ('<no frame>', 0) 224 except Exception as e: 225 code, depth = repr(e), 0 226 227 ctx = (getattr(t, 'context', '(unknown)'),) 228 sctx = getattr(t, 'storedContext', '(unknown)') 229 l = '%s - %s - %s - %s' % (sctx, 230 code, 231 depth, 232 ctx) 233 lines.append(l) 234 235 lines.append('End TaskletDump') 236 if logIt: 237 for l in lines: 238 log.general.Log(l, log.LGINFO) 239 240 return '\n'.join(lines) + '\n' 241 242 243 def KillTasklets(): 244 t = TaskletExt('KillTasklets', KillTasklets_) 245 t() 246 t.run() 247 248 249 def KillTasklets_(): 250 import logmodule as log 251 log.general.Log('killing all %s TaskletExt objects' % len(tasklets), log.LGINFO) 252 for i in range(3): 253 for t in tasklets.keys(): 254 if t is stackless.getcurrent(): 255 continue 256 try: 257 if t.frame: 258 log.general.Log('killing %s' % t, log.LGINFO) 259 t.kill() 260 else: 261 log.general.Log('ignoring %r, no frame.' % t, log.LGINFO) 262 except RuntimeError as e: 263 log.general.Log("couldn't kill %r: %r" % (t, e), log.LGWARN) 264 265 log.general.Log('killing done', log.LGINFO) 266 267 268 class PyResFile(object): 269 __slots__ = ['rf', 270 'name', 271 'mode', 272 'softspace'] 273 274 def __init__(self, path, mode = 'r', bufsize = -1): 275 self.rf = blue.ResFile() 276 self.mode = mode 277 self.name = path 278 if 'w' in mode: 279 try: 280 self.rf.Create(path) 281 except: 282 raise_(IOError, 'could not create ' + path) 283 284 else: 285 readonly = 'a' not in mode and '+' not in mode 286 try: 287 self.rf.OpenAlways(path, readonly, mode) 288 except: 289 raise_(IOError, 'could not open ' + path) 290 291 def read(self, count = 0): 292 try: 293 return self.rf.read(count) 294 except: 295 raise_(IOError, 'could not read %d bytes from %s' % (count, self.rf.filename)) 296 297 def write(self, data): 298 raise NotImplemented 299 300 def readline(self, size = 0): 301 raise NotImplemented 302 303 def readlines(self, sizehint = 0): 304 r = [] 305 while True: 306 l = self.readline() 307 if not l: 308 return r 309 r.append(l) 310 311 def writelines(self, iterable): 312 for i in iterable: 313 self.write(i) 314 315 def seek(self, where, whence = 0): 316 if whence == 1: 317 where += self.rf.pos 318 elif whence == 2: 319 where += self.rf.size 320 try: 321 self.rf.Seek(where) 322 except: 323 raise_(IOError, 'could not seek to pos %d in %s' % (where, self.rf.filename)) 324 325 def tell(self): 326 return self.rf.pos 327 328 def truncate(self, size = None): 329 if size is None: 330 size = self.rf.pos 331 try: 332 self.rf.SetSize(size) 333 except: 334 raise_(IOError, 'could not trucated file %s to %d bytes' % (self.rf.filename, size)) 335 336 def flush(): 337 pass 338 339 def isatty(): 340 return False 341 342 def close(self): 343 self.rf.close() 344 del self.rf 345 346 def next(self): 347 l = self.readline() 348 if l: 349 return l 350 raise StopIteration 351 352 def __iter__(self): 353 return self 354 355 356 PushTimer = ccpProfile.PushTimer 357 PopTimer = ccpProfile.PopTimer 358 CurrentTimer = ccpProfile.CurrentTimer 359 EnterTasklet = ccpProfile.EnterTasklet 360 ReturnFromTasklet = ccpProfile.ReturnFromTasklet 361 Timer = ccpProfile.Timer 362 TimerPush = ccpProfile.TimerPush 363 TimedFunction = ccpProfile.TimedFunction 364 blue.TaskletExt = TaskletExt 365 blue.tasklets = tasklets 366 stackless.taskletext = TaskletExt 367 368 def GetBlueInfo(numMinutes = None, isYield = True): 369 if numMinutes: 370 trend = blue.pyos.cpuUsage[-numMinutes * 60 / 10:] 371 else: 372 trend = blue.pyos.cpuUsage[:] 373 mega = 1.0 / 1024.0 / 1024.0 374 ret = util.KeyVal() 375 ret.memData = [] 376 ret.pymemData = [] 377 ret.bluememData = [] 378 ret.othermemData = [] 379 ret.threadCpuData = [] 380 ret.procCpuData = [] 381 ret.threadKerData = [] 382 ret.procKerData = [] 383 ret.timeData = [] 384 ret.latenessData = [] 385 ret.schedData = [] 386 latenessBase = 100000000.0 387 if len(trend) >= 1: 388 ret.actualmin = int((trend[-1].timestamp - trend[0].timestamp) / 10000000.0 / 60.0) 389 t1 = trend[0].timestamp 390 benice = blue.pyos.BeNice 391 mem = 0 392 for sample in trend: 393 if isYield: 394 benice() 395 elap = sample.timestamp - t1 396 t1 = sample.timestamp 397 p_elap = 100.0 / elap if elap else 0.0 398 ret.memData.append(sample.virtualMemory * mega) 399 ret.pymemData.append(sample.pythonMemoryUsage * mega) 400 thread_u, proc_u = sample.userThreadCpuUsage, sample.userProcessCpuUsage 401 thread_k, proc_k = sample.kernelThreadCpuUsage, sample.kernelProcessCpuUsage 402 thread_cpupct = thread_u * p_elap 403 proc_cpupct = proc_u * p_elap 404 thread_kerpct = thread_k * p_elap 405 proc_kerpct = proc_k * p_elap 406 ret.threadCpuData.append(thread_cpupct) 407 ret.procCpuData.append(proc_cpupct) 408 ret.threadKerData.append(thread_kerpct) 409 ret.procKerData.append(proc_kerpct) 410 sched = (sample.fps, 411 sample.taskletsProcessed, 412 sample.taskletsYielding, 413 sample.taskletsSleeping, 414 sample.taskletsSchedulerDuration, 415 sample.taskletsQueued) 416 ret.schedData.append(sched) 417 ret.timeData.append(sample.timestamp) 418 late = 0.0 419 if elap: 420 late = (elap - latenessBase) / latenessBase * 100 421 ret.latenessData.append(late) 422 423 ret.proc_cpupct = proc_cpupct 424 ret.mem = mem 425 return ret 426 427 428 def get_blue_info_last_tick(): 429 result = {} 430 stats = blue.pyos.cpuUsage[-1:][0] 431 result['virtualmemory'] = stats.virtualMemory 432 result['pymemory'] = stats.pythonMemoryUsage 433 result['workingset'] = stats.workingSetSize 434 result['pagefaults'] = stats.pageFaultCount 435 user_thread, user_process = stats.userThreadCpuUsage, stats.userProcessCpuUsage 436 kernel_thread, kernel_process = stats.kernelThreadCpuUsage, stats.kernelProcessCpuUsage 437 result['user_thread_time_micro'] = user_thread * 0.1 438 result['user_process_time_micro'] = user_process * 0.1 439 result['kernel_thread_time_micro'] = kernel_thread * 0.1 440 result['kernel_process_time_micro'] = kernel_process * 0.1 441 spf = 1.0 / stats.fps if stats.fps > 0.1 else 0 442 result['tasklets_processed'] = stats.taskletsProcessed 443 result['tasklets_queued'] = stats.taskletsQueued 444 result['tasklet_scheduler_duration'] = stats.taskletsSchedulerDuration 445 result['tasklets_sleeping'] = stats.taskletsSleeping 446 result['tasklets_yielding'] = stats.taskletsYielding 447 result['spf'] = spf 448 return result 449 450 451 def Terminate(exit_code, reason = ''): 452 if not isinstance(exit_code, (int, long)): 453 raise TypeError('exit_code must be an integer value.') 454 import logmodule as log 455 if exit_code == 0: 456 log.general.Log('bluepy.Terminate - Reason: %s' % reason, log.LGNOTICE) 457 else: 458 log.general.Log('bluepy.Terminate - Reason: %s' % reason, log.LGERR) 459 try: 460 if 'sm' in __builtins__: 461 sm.ChainEvent('ProcessShutdown') 462 except: 463 log.LogException() 464 465 log.general.Log('Terminate - all ProcessShutdown done', log.LGNOTICE) 466 atexit._run_exitfuncs() 467 log.general.Log('Terminate - atexit done, about to shut down', log.LGNOTICE) 468 blue.os.Terminate(exit_code) 469 470 471 def TerminateSilently(exit_code, reason = ''): 472 if not isinstance(exit_code, (int, long)): 473 raise TypeError('exit_code must be an integer value.') 474 import logmodule as log 475 if exit_code == 0: 476 log.general.Log('bluepy.Terminate - Reason: %s' % reason, log.LGNOTICE) 477 else: 478 log.general.Log('bluepy.Terminate - Reason: %s' % reason, log.LGERR) 479 atexit._run_exitfuncs() 480 blue.os.Terminate(exit_code)