Show More
@@ -0,0 +1,119 b'' | |||||
|
1 | # this is copied from the lsprof distro because somehow | |||
|
2 | # it is not installed by distutils | |||
|
3 | # | |||
|
4 | # small modifications made | |||
|
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, limit=None, climit=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 %11.4f %11.4f %s\n" | |||
|
47 | hcols = "% 12s %12s %12s %s\n" | |||
|
48 | cols2 = "+%12s %11.4f %11.4f + %s\n" | |||
|
49 | file.write(hcols % ("CallCount", "Total(s)", | |||
|
50 | "Inline(s)", "module:lineno(function)")) | |||
|
51 | count = 0 | |||
|
52 | for e in d: | |||
|
53 | file.write(cols % (e.callcount, e.totaltime, | |||
|
54 | e.inlinetime, label(e.code))) | |||
|
55 | count += 1 | |||
|
56 | if limit is not None and count == limit: | |||
|
57 | return | |||
|
58 | ccount = 0 | |||
|
59 | if e.calls: | |||
|
60 | for se in e.calls: | |||
|
61 | file.write(cols % ("+%s" % se.callcount, | |||
|
62 | se.totaltime, se.inlinetime, | |||
|
63 | "+%s" % label(se.code))) | |||
|
64 | count += 1 | |||
|
65 | ccount += 1 | |||
|
66 | if limit is not None and count == limit: | |||
|
67 | return | |||
|
68 | if climit is not None and ccount == climit: | |||
|
69 | break | |||
|
70 | ||||
|
71 | def freeze(self): | |||
|
72 | """Replace all references to code objects with string | |||
|
73 | descriptions; this makes it possible to pickle the instance.""" | |||
|
74 | ||||
|
75 | # this code is probably rather ickier than it needs to be! | |||
|
76 | for i in range(len(self.data)): | |||
|
77 | e = self.data[i] | |||
|
78 | if not isinstance(e.code, str): | |||
|
79 | self.data[i] = type(e)((label(e.code),) + e[1:]) | |||
|
80 | if e.calls: | |||
|
81 | for j in range(len(e.calls)): | |||
|
82 | se = e.calls[j] | |||
|
83 | if not isinstance(se.code, str): | |||
|
84 | e.calls[j] = type(se)((label(se.code),) + se[1:]) | |||
|
85 | ||||
|
86 | _fn2mod = {} | |||
|
87 | ||||
|
88 | def label(code): | |||
|
89 | if isinstance(code, str): | |||
|
90 | return code | |||
|
91 | try: | |||
|
92 | mname = _fn2mod[code.co_filename] | |||
|
93 | except KeyError: | |||
|
94 | for k, v in sys.modules.iteritems(): | |||
|
95 | if v is None: | |||
|
96 | continue | |||
|
97 | if not hasattr(v, '__file__'): | |||
|
98 | continue | |||
|
99 | if not isinstance(v.__file__, str): | |||
|
100 | continue | |||
|
101 | if v.__file__.startswith(code.co_filename): | |||
|
102 | mname = _fn2mod[code.co_filename] = k | |||
|
103 | break | |||
|
104 | else: | |||
|
105 | mname = _fn2mod[code.co_filename] = '<%s>'%code.co_filename | |||
|
106 | ||||
|
107 | return '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name) | |||
|
108 | ||||
|
109 | ||||
|
110 | if __name__ == '__main__': | |||
|
111 | import os | |||
|
112 | sys.argv = sys.argv[1:] | |||
|
113 | if not sys.argv: | |||
|
114 | print >> sys.stderr, "usage: lsprof.py <script> <arguments...>" | |||
|
115 | sys.exit(2) | |||
|
116 | sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0]))) | |||
|
117 | stats = profile(execfile, sys.argv[0], globals(), locals()) | |||
|
118 | stats.sort() | |||
|
119 | stats.pprint() |
@@ -3158,6 +3158,7 b' globalopts = [' | |||||
3158 | ('', 'config', [], _('set/override config option')), |
|
3158 | ('', 'config', [], _('set/override config option')), | |
3159 | ('', 'debug', None, _('enable debugging output')), |
|
3159 | ('', 'debug', None, _('enable debugging output')), | |
3160 | ('', 'debugger', None, _('start debugger')), |
|
3160 | ('', 'debugger', None, _('start debugger')), | |
|
3161 | ('', 'lsprof', None, _('print improved command execution profile')), | |||
3161 | ('', 'traceback', None, _('print traceback on exception')), |
|
3162 | ('', 'traceback', None, _('print traceback on exception')), | |
3162 | ('', 'time', None, _('time how long the command takes')), |
|
3163 | ('', 'time', None, _('time how long the command takes')), | |
3163 | ('', 'profile', None, _('print command execution profile')), |
|
3164 | ('', 'profile', None, _('print command execution profile')), | |
@@ -3385,6 +3386,22 b' def dispatch(args):' | |||||
3385 | stats.strip_dirs() |
|
3386 | stats.strip_dirs() | |
3386 | stats.sort_stats('time', 'calls') |
|
3387 | stats.sort_stats('time', 'calls') | |
3387 | stats.print_stats(40) |
|
3388 | stats.print_stats(40) | |
|
3389 | elif options['lsprof']: | |||
|
3390 | try: | |||
|
3391 | from mercurial import lsprof | |||
|
3392 | except ImportError: | |||
|
3393 | raise util.Abort(_( | |||
|
3394 | 'lsprof not available - install from ' | |||
|
3395 | 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/')) | |||
|
3396 | p = lsprof.Profiler() | |||
|
3397 | p.enable(subcalls=True) | |||
|
3398 | try: | |||
|
3399 | return d() | |||
|
3400 | finally: | |||
|
3401 | p.disable() | |||
|
3402 | stats = lsprof.Stats(p.getstats()) | |||
|
3403 | stats.sort() | |||
|
3404 | stats.pprint(top=10, file=sys.stderr, climit=5) | |||
3388 | else: |
|
3405 | else: | |
3389 | return d() |
|
3406 | return d() | |
3390 | finally: |
|
3407 | finally: |
General Comments 0
You need to be logged in to leave comments.
Login now