Mercurial > hg
annotate mercurial/lsprof.py @ 25561:50a6c3c55db1 stable
parsers: do not cache RevlogError type (issue4451)
Index lookups raise RevlogError when the lookup fails. The previous
implementation was caching a reference to the RevlogError type in a
static variable. This assumed that the "mercurial.error" module was
only loaded once and there was only a single copy of it floating
around in memory. Unfortunately, in some situations - including
certain mod_wsgi configurations - this was not the case: the
"mercurial.error" module could be reloaded. It was possible for a
"RevlogError" reference from the first interpreter to be used by
a second interpreter. While the underlying thing was a
"mercurial.error.RevlogError," the object IDs were different, so
the Python code in revlog.py was failing to catch the exception! This
error has existed since the C index lookup code was implemented in
changeset e8d37b78acfb, which was first released in Mercurial 2.2 in
2012.
http://emptysqua.re/blog/python-c-extensions-and-mod-wsgi/#static-variables-are-shared
contains more details.
This patch removes the caching of the RevlogError type from the
function.
Since pretty much the entire function was refactored and the return
value of the function wasn't used, I changed the function signature
to not return anything.
For reasons unknown to me, we were calling PyErr_SetObject()
with the type of RevlogError and an instance of RevlogError. This
was equivalent to the Python code "raise RevlogError(RevlogError)".
This seemed wonky and completely unnecessary. The Python code only
cares about the type of the exception, not its contents. So I got
rid of this complexity.
This is my first Python C extension patch. Please give extra scrutiny
to it during review.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Fri, 12 Jun 2015 14:43:59 -0700 |
parents | a40d608e2a7b |
children | 9c75daf89450 |
rev | line source |
---|---|
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
1 import sys |
6212 | 2 from _lsprof import Profiler, profiler_entry |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
3 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
4 __all__ = ['profile', 'Stats'] |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
5 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
6 def profile(f, *args, **kwds): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
7 """XXX docstring""" |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
8 p = Profiler() |
5992
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
9 p.enable(subcalls=True, builtins=True) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
10 try: |
5992
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
11 f(*args, **kwds) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
12 finally: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
13 p.disable() |
5992
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
14 return Stats(p.getstats()) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
15 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
16 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
17 class Stats(object): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
18 """XXX docstring""" |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
19 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
20 def __init__(self, data): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
21 self.data = data |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
22 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
23 def sort(self, crit="inlinetime"): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
24 """XXX docstring""" |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
25 if crit not in profiler_entry.__dict__: |
7008
8fee8ff13d37
use Exception(args)-style raising consistently (py3k compatibility)
Peter Ruibal <peter.ruibal@intel.com>
parents:
6212
diff
changeset
|
26 raise ValueError("Can't sort by %s" % crit) |
9032
1fa80c5428b8
compat: use 'key' argument instead of 'cmp' when sorting a list
Alejandro Santos <alejolp@alejolp.com>
parents:
7875
diff
changeset
|
27 self.data.sort(key=lambda x: getattr(x, crit), reverse=True) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
28 for e in self.data: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
29 if e.calls: |
9032
1fa80c5428b8
compat: use 'key' argument instead of 'cmp' when sorting a list
Alejandro Santos <alejolp@alejolp.com>
parents:
7875
diff
changeset
|
30 e.calls.sort(key=lambda x: getattr(x, crit), reverse=True) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
31 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
32 def pprint(self, top=None, file=None, limit=None, climit=None): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
33 """XXX docstring""" |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
34 if file is None: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
35 file = sys.stdout |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
36 d = self.data |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
37 if top is not None: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
38 d = d[:top] |
5992
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
39 cols = "% 12s %12s %11.4f %11.4f %s\n" |
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
40 hcols = "% 12s %12s %12s %12s %s\n" |
16804
a455a18bfdac
lsprof: report units correctly
Bryan O'Sullivan <bryano@fb.com>
parents:
16263
diff
changeset
|
41 file.write(hcols % ("CallCount", "Recursive", "Total(s)", |
a455a18bfdac
lsprof: report units correctly
Bryan O'Sullivan <bryano@fb.com>
parents:
16263
diff
changeset
|
42 "Inline(s)", "module:lineno(function)")) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
43 count = 0 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
44 for e in d: |
5992
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
45 file.write(cols % (e.callcount, e.reccallcount, e.totaltime, |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
46 e.inlinetime, label(e.code))) |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
47 count += 1 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
48 if limit is not None and count == limit: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
49 return |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
50 ccount = 0 |
16263
be92ddc636e3
profile: add undocumented config options for profiler output
Matt Mackall <mpm@selenic.com>
parents:
14959
diff
changeset
|
51 if climit and e.calls: |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
52 for se in e.calls: |
18642
a40d608e2a7b
profiling: replace '+' markup of nested lines with indentation
Mads Kiilerich <mads@kiilerich.com>
parents:
16804
diff
changeset
|
53 file.write(cols % (se.callcount, se.reccallcount, |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
54 se.totaltime, se.inlinetime, |
18642
a40d608e2a7b
profiling: replace '+' markup of nested lines with indentation
Mads Kiilerich <mads@kiilerich.com>
parents:
16804
diff
changeset
|
55 " %s" % label(se.code))) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
56 count += 1 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
57 ccount += 1 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
58 if limit is not None and count == limit: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
59 return |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
60 if climit is not None and ccount == climit: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
61 break |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
62 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
63 def freeze(self): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
64 """Replace all references to code objects with string |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
65 descriptions; this makes it possible to pickle the instance.""" |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
66 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
67 # this code is probably rather ickier than it needs to be! |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
68 for i in range(len(self.data)): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
69 e = self.data[i] |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
70 if not isinstance(e.code, str): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
71 self.data[i] = type(e)((label(e.code),) + e[1:]) |
5992
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
72 if e.calls: |
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
73 for j in range(len(e.calls)): |
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
74 se = e.calls[j] |
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
75 if not isinstance(se.code, str): |
30c40ba10963
updating lsprof.py from remote repository
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
2497
diff
changeset
|
76 e.calls[j] = type(se)((label(se.code),) + se[1:]) |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
77 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
78 _fn2mod = {} |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
79 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
80 def label(code): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
81 if isinstance(code, str): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
82 return code |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
83 try: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
84 mname = _fn2mod[code.co_filename] |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
85 except KeyError: |
9314
3f93f6838639
lsprof: make profile not die when imported modules changes (issue1774)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
7875
diff
changeset
|
86 for k, v in list(sys.modules.iteritems()): |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
87 if v is None: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
88 continue |
14959
b1dcc5ab86cd
lsprof: use getattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents:
12842
diff
changeset
|
89 if not isinstance(getattr(v, '__file__', None), str): |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
90 continue |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
91 if v.__file__.startswith(code.co_filename): |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
92 mname = _fn2mod[code.co_filename] = k |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
93 break |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
94 else: |
10339
23e608f42f2c
fix spaces/identation issues
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
9316
diff
changeset
|
95 mname = _fn2mod[code.co_filename] = '<%s>' % code.co_filename |
2422
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
96 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
97 return '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name) |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
98 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
99 |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
100 if __name__ == '__main__': |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
101 import os |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
102 sys.argv = sys.argv[1:] |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
103 if not sys.argv: |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
104 print >> sys.stderr, "usage: lsprof.py <script> <arguments...>" |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
105 sys.exit(2) |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
106 sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0]))) |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
107 stats = profile(execfile, sys.argv[0], globals(), locals()) |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
108 stats.sort() |
6aa75e77cafe
add --lsprof option. 3x faster than --profile, more useful output.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff
changeset
|
109 stats.pprint() |