bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
1185.33.86
by Martin Pool
 Add additional module for lsprof.  | 
1  | 
# this is copied from the lsprof distro because somehow
 | 
2  | 
# it is not installed by distutils
 | 
|
3  | 
# I made one modification to profile so that it returns a pair
 | 
|
4  | 
# instead of just the Stats object
 | 
|
5  | 
||
6  | 
import sys  | 
|
7  | 
from _lsprof import Profiler, profiler_entry, profiler_subentry  | 
|
8  | 
||
9  | 
__all__ = ['profile', 'Stats']  | 
|
10  | 
||
11  | 
def profile(f, *args, **kwds):  | 
|
12  | 
"""XXX docstring"""  | 
|
13  | 
p = Profiler()  | 
|
14  | 
p.enable(subcalls=True)  | 
|
15  | 
try:  | 
|
16  | 
ret = f(*args, **kwds)  | 
|
17  | 
finally:  | 
|
18  | 
p.disable()  | 
|
19  | 
return ret,Stats(p.getstats())  | 
|
20  | 
||
21  | 
||
22  | 
class Stats(object):  | 
|
23  | 
"""XXX docstring"""  | 
|
24  | 
||
25  | 
def __init__(self, data):  | 
|
26  | 
self.data = data  | 
|
27  | 
||
28  | 
def sort(self, crit="inlinetime"):  | 
|
29  | 
"""XXX docstring"""  | 
|
30  | 
if crit not in profiler_entry.__dict__:  | 
|
31  | 
raise ValueError, "Can't sort by %s" % crit  | 
|
32  | 
self.data.sort(lambda b, a: cmp(getattr(a, crit),  | 
|
33  | 
getattr(b, crit)))  | 
|
34  | 
for e in self.data:  | 
|
35  | 
if e.calls:  | 
|
36  | 
e.calls.sort(lambda b, a: cmp(getattr(a, crit),  | 
|
37  | 
getattr(b, crit)))  | 
|
38  | 
||
39  | 
def pprint(self, top=None, file=None):  | 
|
40  | 
"""XXX docstring"""  | 
|
41  | 
if file is None:  | 
|
42  | 
file = sys.stdout  | 
|
43  | 
d = self.data  | 
|
44  | 
if top is not None:  | 
|
45  | 
d = d[:top]  | 
|
46  | 
cols = "% 12s %12s %11.4f %11.4f %s\n"  | 
|
47  | 
hcols = "% 12s %12s %12s %12s %s\n"  | 
|
48  | 
cols2 = "+%12s %12s %11.4f %11.4f + %s\n"  | 
|
49  | 
file.write(hcols % ("CallCount", "Recursive", "Total(ms)",  | 
|
50  | 
"Inline(ms)", "module:lineno(function)"))  | 
|
51  | 
for e in d:  | 
|
52  | 
file.write(cols % (e.callcount, e.reccallcount, e.totaltime,  | 
|
53  | 
e.inlinetime, label(e.code)))  | 
|
54  | 
if e.calls:  | 
|
55  | 
for se in e.calls:  | 
|
56  | 
file.write(cols % ("+%s" % se.callcount, se.reccallcount,  | 
|
57  | 
se.totaltime, se.inlinetime,  | 
|
58  | 
"+%s" % label(se.code)))  | 
|
59  | 
||
60  | 
def freeze(self):  | 
|
61  | 
"""Replace all references to code objects with string  | 
|
62  | 
        descriptions; this makes it possible to pickle the instance."""
 | 
|
63  | 
||
64  | 
        # this code is probably rather ickier than it needs to be!
 | 
|
65  | 
for i in range(len(self.data)):  | 
|
66  | 
e = self.data[i]  | 
|
67  | 
if not isinstance(e.code, str):  | 
|
68  | 
self.data[i] = type(e)((label(e.code),) + e[1:])  | 
|
69  | 
if e.calls:  | 
|
70  | 
for j in range(len(e.calls)):  | 
|
71  | 
se = e.calls[j]  | 
|
72  | 
if not isinstance(se.code, str):  | 
|
73  | 
e.calls[j] = type(se)((label(se.code),) + se[1:])  | 
|
74  | 
||
75  | 
_fn2mod = {}  | 
|
76  | 
||
77  | 
def label(code):  | 
|
78  | 
if isinstance(code, str):  | 
|
79  | 
return code  | 
|
80  | 
try:  | 
|
81  | 
mname = _fn2mod[code.co_filename]  | 
|
82  | 
except KeyError:  | 
|
83  | 
for k, v in sys.modules.iteritems():  | 
|
84  | 
if v is None:  | 
|
85  | 
                continue
 | 
|
86  | 
if not hasattr(v, '__file__'):  | 
|
87  | 
                continue
 | 
|
88  | 
if not isinstance(v.__file__, str):  | 
|
89  | 
                continue
 | 
|
90  | 
if v.__file__.startswith(code.co_filename):  | 
|
91  | 
mname = _fn2mod[code.co_filename] = k  | 
|
92  | 
                break
 | 
|
93  | 
else:  | 
|
94  | 
mname = _fn2mod[code.co_filename] = '<%s>'%code.co_filename  | 
|
95  | 
||
96  | 
return '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name)  | 
|
97  | 
||
98  | 
||
99  | 
if __name__ == '__main__':  | 
|
100  | 
import os  | 
|
101  | 
sys.argv = sys.argv[1:]  | 
|
102  | 
if not sys.argv:  | 
|
103  | 
print >> sys.stderr, "usage: lsprof.py <script> <arguments...>"  | 
|
104  | 
sys.exit(2)  | 
|
105  | 
sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])))  | 
|
106  | 
stats = profile(execfile, sys.argv[0], globals(), locals())  | 
|
107  | 
stats.sort()  | 
|
108  | 
stats.pprint()  |