0001 """Statistics analyzer for HotShot.""" 0002 0003 import profile 0004 import pstats 0005 0006 import hotshot.log 0007 0008 from hotshot.log import ENTER, EXIT 0009 0010 0011 def load(filename): 0012 return StatsLoader(filename).load() 0013 0014 0015 class StatsLoader: 0016 def __init__(self, logfn): 0017 self._logfn = logfn 0018 self._code = {} 0019 self._stack = [] 0020 self.pop_frame = self._stack.pop 0021 0022 def load(self): 0023 # The timer selected by the profiler should never be used, so make 0024 # sure it doesn't work: 0025 p = Profile() 0026 p.get_time = _brokentimer 0027 log = hotshot.log.LogReader(self._logfn) 0028 taccum = 0 0029 for event in log: 0030 what, (filename, lineno, funcname), tdelta = event 0031 if tdelta > 0: 0032 taccum += tdelta 0033 0034 # We multiply taccum to convert from the microseconds we 0035 # have to the seconds that the profile/pstats module work 0036 # with; this allows the numbers to have some basis in 0037 # reality (ignoring calibration issues for now). 0038 0039 if what == ENTER: 0040 frame = self.new_frame(filename, lineno, funcname) 0041 p.trace_dispatch_call(frame, taccum * .000001) 0042 taccum = 0 0043 0044 elif what == EXIT: 0045 frame = self.pop_frame() 0046 p.trace_dispatch_return(frame, taccum * .000001) 0047 taccum = 0 0048 0049 # no further work for line events 0050 0051 assert not self._stack 0052 return pstats.Stats(p) 0053 0054 def new_frame(self, *args): 0055 # args must be filename, firstlineno, funcname 0056 # our code objects are cached since we don't need to create 0057 # new ones every time 0058 try: 0059 code = self._code[args] 0060 except KeyError: 0061 code = FakeCode(*args) 0062 self._code[args] = code 0063 # frame objects are create fresh, since the back pointer will 0064 # vary considerably 0065 if self._stack: 0066 back = self._stack[-1] 0067 else: 0068 back = None 0069 frame = FakeFrame(code, back) 0070 self._stack.append(frame) 0071 return frame 0072 0073 0074 class Profile(profile.Profile): 0075 def simulate_cmd_complete(self): 0076 pass 0077 0078 0079 class FakeCode: 0080 def __init__(self, filename, firstlineno, funcname): 0081 self.co_filename = filename 0082 self.co_firstlineno = firstlineno 0083 self.co_name = self.__name__ = funcname 0084 0085 0086 class FakeFrame: 0087 def __init__(self, code, back): 0088 self.f_back = back 0089 self.f_code = code 0090 0091 0092 def _brokentimer(): 0093 raise RuntimeError, "this timer should not be called" 0094
Generated by PyXR 0.9.4