Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 47cada7

Browse files
committed
pstats-compatible analysis module.
hotshot.stats.load(logfilename) returns a pstats.Stats instance, which is about as compatible as it gets.
1 parent e7d8a78 commit 47cada7

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

Lib/hotshot/stats.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""Statistics analyzer for HotShot."""
2+
3+
import profile
4+
import pstats
5+
6+
import hotshot.log
7+
8+
from hotshot.log import ENTER, EXIT
9+
10+
11+
def load(filename):
12+
return StatsLoader(filename).load()
13+
14+
15+
class StatsLoader:
16+
def __init__(self, logfn):
17+
self._logfn = logfn
18+
self._code = {}
19+
self._stack = []
20+
self.pop_frame = self._stack.pop
21+
22+
def load(self):
23+
# The timer selected by the profiler should never be used, so make
24+
# sure it doesn't work:
25+
p = Profile()
26+
p.get_time = _brokentimer
27+
log = hotshot.log.LogReader(self._logfn)
28+
taccum = 0
29+
for event in log:
30+
what, (filename, lineno, funcname), tdelta = event
31+
if tdelta > 0:
32+
taccum += tdelta
33+
34+
# We multiply taccum to convert from the microseconds we
35+
# have to the seconds that the profile/pstats module work
36+
# with; this allows the numbers to have some basis in
37+
# reality (ignoring calibration issues for now).
38+
39+
if what == ENTER:
40+
frame = self.new_frame(filename, lineno, funcname)
41+
p.trace_dispatch_call(frame, taccum * .000001)
42+
taccum = 0
43+
44+
elif what == EXIT:
45+
frame = self.pop_frame()
46+
p.trace_dispatch_return(frame, taccum * .000001)
47+
taccum = 0
48+
49+
# no further work for line events
50+
51+
assert not self._stack
52+
return pstats.Stats(p)
53+
54+
def new_frame(self, *args):
55+
# args must be filename, firstlineno, funcname
56+
# our code objects are cached since we don't need to create
57+
# new ones every time
58+
try:
59+
code = self._code[args]
60+
except KeyError:
61+
code = FakeCode(*args)
62+
self._code[args] = code
63+
# frame objects are create fresh, since the back pointer will
64+
# vary considerably
65+
if self._stack:
66+
back = self._stack[-1]
67+
else:
68+
back = None
69+
frame = FakeFrame(code, back)
70+
self._stack.append(frame)
71+
return frame
72+
73+
74+
class Profile(profile.Profile):
75+
def simulate_cmd_complete(self):
76+
pass
77+
78+
79+
class FakeCode:
80+
def __init__(self, filename, firstlineno, funcname):
81+
self.co_filename = filename
82+
self.co_firstlineno = firstlineno
83+
self.co_name = self.__name__ = funcname
84+
85+
86+
class FakeFrame:
87+
def __init__(self, code, back):
88+
self.f_back = back
89+
self.f_code = code
90+
91+
92+
def _brokentimer():
93+
raise RuntimeError, "this timer should not be called"

0 commit comments

Comments
 (0)