##// END OF EJS Templates
lsprof: remove __main__ functionality...
Gregory Szorc -
r43378:dc6d866b default
parent child Browse files
Show More
@@ -1,158 +1,145 b''
1 from __future__ import absolute_import, print_function
1 from __future__ import absolute_import, print_function
2
2
3 import _lsprof
3 import _lsprof
4 import sys
4 import sys
5
5
6 from .pycompat import getattr
6 from .pycompat import getattr
7 from . import pycompat
7 from . import pycompat
8
8
9 Profiler = _lsprof.Profiler
9 Profiler = _lsprof.Profiler
10
10
11 # PyPy doesn't expose profiler_entry from the module.
11 # PyPy doesn't expose profiler_entry from the module.
12 profiler_entry = getattr(_lsprof, 'profiler_entry', None)
12 profiler_entry = getattr(_lsprof, 'profiler_entry', None)
13
13
14 __all__ = [b'profile', b'Stats']
14 __all__ = [b'profile', b'Stats']
15
15
16
16
17 def profile(f, *args, **kwds):
17 def profile(f, *args, **kwds):
18 """XXX docstring"""
18 """XXX docstring"""
19 p = Profiler()
19 p = Profiler()
20 p.enable(subcalls=True, builtins=True)
20 p.enable(subcalls=True, builtins=True)
21 try:
21 try:
22 f(*args, **kwds)
22 f(*args, **kwds)
23 finally:
23 finally:
24 p.disable()
24 p.disable()
25 return Stats(p.getstats())
25 return Stats(p.getstats())
26
26
27
27
28 class Stats(object):
28 class Stats(object):
29 """XXX docstring"""
29 """XXX docstring"""
30
30
31 def __init__(self, data):
31 def __init__(self, data):
32 self.data = data
32 self.data = data
33
33
34 def sort(self, crit=r"inlinetime"):
34 def sort(self, crit=r"inlinetime"):
35 """XXX docstring"""
35 """XXX docstring"""
36 # profiler_entries isn't defined when running under PyPy.
36 # profiler_entries isn't defined when running under PyPy.
37 if profiler_entry:
37 if profiler_entry:
38 if crit not in profiler_entry.__dict__:
38 if crit not in profiler_entry.__dict__:
39 raise ValueError(b"Can't sort by %s" % crit)
39 raise ValueError(b"Can't sort by %s" % crit)
40 elif self.data and not getattr(self.data[0], crit, None):
40 elif self.data and not getattr(self.data[0], crit, None):
41 raise ValueError(b"Can't sort by %s" % crit)
41 raise ValueError(b"Can't sort by %s" % crit)
42
42
43 self.data.sort(key=lambda x: getattr(x, crit), reverse=True)
43 self.data.sort(key=lambda x: getattr(x, crit), reverse=True)
44 for e in self.data:
44 for e in self.data:
45 if e.calls:
45 if e.calls:
46 e.calls.sort(key=lambda x: getattr(x, crit), reverse=True)
46 e.calls.sort(key=lambda x: getattr(x, crit), reverse=True)
47
47
48 def pprint(self, top=None, file=None, limit=None, climit=None):
48 def pprint(self, top=None, file=None, limit=None, climit=None):
49 """XXX docstring"""
49 """XXX docstring"""
50 if file is None:
50 if file is None:
51 file = sys.stdout
51 file = sys.stdout
52 d = self.data
52 d = self.data
53 if top is not None:
53 if top is not None:
54 d = d[:top]
54 d = d[:top]
55 cols = b"% 12d %12d %11.4f %11.4f %s\n"
55 cols = b"% 12d %12d %11.4f %11.4f %s\n"
56 hcols = b"% 12s %12s %12s %12s %s\n"
56 hcols = b"% 12s %12s %12s %12s %s\n"
57 file.write(
57 file.write(
58 hcols
58 hcols
59 % (
59 % (
60 b"CallCount",
60 b"CallCount",
61 b"Recursive",
61 b"Recursive",
62 b"Total(s)",
62 b"Total(s)",
63 b"Inline(s)",
63 b"Inline(s)",
64 b"module:lineno(function)",
64 b"module:lineno(function)",
65 )
65 )
66 )
66 )
67 count = 0
67 count = 0
68 for e in d:
68 for e in d:
69 file.write(
69 file.write(
70 cols
70 cols
71 % (
71 % (
72 e.callcount,
72 e.callcount,
73 e.reccallcount,
73 e.reccallcount,
74 e.totaltime,
74 e.totaltime,
75 e.inlinetime,
75 e.inlinetime,
76 label(e.code),
76 label(e.code),
77 )
77 )
78 )
78 )
79 count += 1
79 count += 1
80 if limit is not None and count == limit:
80 if limit is not None and count == limit:
81 return
81 return
82 ccount = 0
82 ccount = 0
83 if climit and e.calls:
83 if climit and e.calls:
84 for se in e.calls:
84 for se in e.calls:
85 file.write(
85 file.write(
86 cols
86 cols
87 % (
87 % (
88 se.callcount,
88 se.callcount,
89 se.reccallcount,
89 se.reccallcount,
90 se.totaltime,
90 se.totaltime,
91 se.inlinetime,
91 se.inlinetime,
92 b" %s" % label(se.code),
92 b" %s" % label(se.code),
93 )
93 )
94 )
94 )
95 count += 1
95 count += 1
96 ccount += 1
96 ccount += 1
97 if limit is not None and count == limit:
97 if limit is not None and count == limit:
98 return
98 return
99 if climit is not None and ccount == climit:
99 if climit is not None and ccount == climit:
100 break
100 break
101
101
102 def freeze(self):
102 def freeze(self):
103 """Replace all references to code objects with string
103 """Replace all references to code objects with string
104 descriptions; this makes it possible to pickle the instance."""
104 descriptions; this makes it possible to pickle the instance."""
105
105
106 # this code is probably rather ickier than it needs to be!
106 # this code is probably rather ickier than it needs to be!
107 for i in range(len(self.data)):
107 for i in range(len(self.data)):
108 e = self.data[i]
108 e = self.data[i]
109 if not isinstance(e.code, str):
109 if not isinstance(e.code, str):
110 self.data[i] = type(e)((label(e.code),) + e[1:])
110 self.data[i] = type(e)((label(e.code),) + e[1:])
111 if e.calls:
111 if e.calls:
112 for j in range(len(e.calls)):
112 for j in range(len(e.calls)):
113 se = e.calls[j]
113 se = e.calls[j]
114 if not isinstance(se.code, str):
114 if not isinstance(se.code, str):
115 e.calls[j] = type(se)((label(se.code),) + se[1:])
115 e.calls[j] = type(se)((label(se.code),) + se[1:])
116
116
117
117
118 _fn2mod = {}
118 _fn2mod = {}
119
119
120
120
121 def label(code):
121 def label(code):
122 if isinstance(code, str):
122 if isinstance(code, str):
123 if sys.version_info.major >= 3:
123 if sys.version_info.major >= 3:
124 code = code.encode('latin-1')
124 code = code.encode('latin-1')
125 return code
125 return code
126 try:
126 try:
127 mname = _fn2mod[code.co_filename]
127 mname = _fn2mod[code.co_filename]
128 except KeyError:
128 except KeyError:
129 for k, v in list(pycompat.iteritems(sys.modules)):
129 for k, v in list(pycompat.iteritems(sys.modules)):
130 if v is None:
130 if v is None:
131 continue
131 continue
132 if not isinstance(getattr(v, '__file__', None), str):
132 if not isinstance(getattr(v, '__file__', None), str):
133 continue
133 continue
134 if v.__file__.startswith(code.co_filename):
134 if v.__file__.startswith(code.co_filename):
135 mname = _fn2mod[code.co_filename] = k
135 mname = _fn2mod[code.co_filename] = k
136 break
136 break
137 else:
137 else:
138 mname = _fn2mod[code.co_filename] = r'<%s>' % code.co_filename
138 mname = _fn2mod[code.co_filename] = r'<%s>' % code.co_filename
139
139
140 res = r'%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name)
140 res = r'%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name)
141
141
142 if sys.version_info.major >= 3:
142 if sys.version_info.major >= 3:
143 res = res.encode('latin-1')
143 res = res.encode('latin-1')
144
144
145 return res
145 return res
146
147
148 if __name__ == '__main__':
149 import os
150
151 sys.argv = sys.argv[1:]
152 if not sys.argv:
153 print(b"usage: lsprof.py <script> <arguments...>", file=sys.stderr)
154 sys.exit(2)
155 sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])))
156 stats = profile(execfile, sys.argv[0], globals(), locals())
157 stats.sort()
158 stats.pprint()
General Comments 0
You need to be logged in to leave comments. Login now