##// END OF EJS Templates
lsprof: make profile not die when imported modules changes (issue1774)
Dirkjan Ochtman -
r9314:3f93f683 default
parent child Browse files
Show More
@@ -1,115 +1,115 b''
1 #! /usr/bin/env python
1 #! /usr/bin/env python
2
2
3 import sys
3 import sys
4 from _lsprof import Profiler, profiler_entry
4 from _lsprof import Profiler, profiler_entry
5
5
6 __all__ = ['profile', 'Stats']
6 __all__ = ['profile', 'Stats']
7
7
8 def profile(f, *args, **kwds):
8 def profile(f, *args, **kwds):
9 """XXX docstring"""
9 """XXX docstring"""
10 p = Profiler()
10 p = Profiler()
11 p.enable(subcalls=True, builtins=True)
11 p.enable(subcalls=True, builtins=True)
12 try:
12 try:
13 f(*args, **kwds)
13 f(*args, **kwds)
14 finally:
14 finally:
15 p.disable()
15 p.disable()
16 return Stats(p.getstats())
16 return Stats(p.getstats())
17
17
18
18
19 class Stats(object):
19 class Stats(object):
20 """XXX docstring"""
20 """XXX docstring"""
21
21
22 def __init__(self, data):
22 def __init__(self, data):
23 self.data = data
23 self.data = data
24
24
25 def sort(self, crit="inlinetime"):
25 def sort(self, crit="inlinetime"):
26 """XXX docstring"""
26 """XXX docstring"""
27 if crit not in profiler_entry.__dict__:
27 if crit not in profiler_entry.__dict__:
28 raise ValueError("Can't sort by %s" % crit)
28 raise ValueError("Can't sort by %s" % crit)
29 self.data.sort(lambda b, a: cmp(getattr(a, crit),
29 self.data.sort(lambda b, a: cmp(getattr(a, crit),
30 getattr(b, crit)))
30 getattr(b, crit)))
31 for e in self.data:
31 for e in self.data:
32 if e.calls:
32 if e.calls:
33 e.calls.sort(lambda b, a: cmp(getattr(a, crit),
33 e.calls.sort(lambda b, a: cmp(getattr(a, crit),
34 getattr(b, crit)))
34 getattr(b, crit)))
35
35
36 def pprint(self, top=None, file=None, limit=None, climit=None):
36 def pprint(self, top=None, file=None, limit=None, climit=None):
37 """XXX docstring"""
37 """XXX docstring"""
38 if file is None:
38 if file is None:
39 file = sys.stdout
39 file = sys.stdout
40 d = self.data
40 d = self.data
41 if top is not None:
41 if top is not None:
42 d = d[:top]
42 d = d[:top]
43 cols = "% 12s %12s %11.4f %11.4f %s\n"
43 cols = "% 12s %12s %11.4f %11.4f %s\n"
44 hcols = "% 12s %12s %12s %12s %s\n"
44 hcols = "% 12s %12s %12s %12s %s\n"
45 file.write(hcols % ("CallCount", "Recursive", "Total(ms)",
45 file.write(hcols % ("CallCount", "Recursive", "Total(ms)",
46 "Inline(ms)", "module:lineno(function)"))
46 "Inline(ms)", "module:lineno(function)"))
47 count = 0
47 count = 0
48 for e in d:
48 for e in d:
49 file.write(cols % (e.callcount, e.reccallcount, e.totaltime,
49 file.write(cols % (e.callcount, e.reccallcount, e.totaltime,
50 e.inlinetime, label(e.code)))
50 e.inlinetime, label(e.code)))
51 count += 1
51 count += 1
52 if limit is not None and count == limit:
52 if limit is not None and count == limit:
53 return
53 return
54 ccount = 0
54 ccount = 0
55 if e.calls:
55 if e.calls:
56 for se in e.calls:
56 for se in e.calls:
57 file.write(cols % ("+%s" % se.callcount, se.reccallcount,
57 file.write(cols % ("+%s" % se.callcount, se.reccallcount,
58 se.totaltime, se.inlinetime,
58 se.totaltime, se.inlinetime,
59 "+%s" % label(se.code)))
59 "+%s" % label(se.code)))
60 count += 1
60 count += 1
61 ccount += 1
61 ccount += 1
62 if limit is not None and count == limit:
62 if limit is not None and count == limit:
63 return
63 return
64 if climit is not None and ccount == climit:
64 if climit is not None and ccount == climit:
65 break
65 break
66
66
67 def freeze(self):
67 def freeze(self):
68 """Replace all references to code objects with string
68 """Replace all references to code objects with string
69 descriptions; this makes it possible to pickle the instance."""
69 descriptions; this makes it possible to pickle the instance."""
70
70
71 # this code is probably rather ickier than it needs to be!
71 # this code is probably rather ickier than it needs to be!
72 for i in range(len(self.data)):
72 for i in range(len(self.data)):
73 e = self.data[i]
73 e = self.data[i]
74 if not isinstance(e.code, str):
74 if not isinstance(e.code, str):
75 self.data[i] = type(e)((label(e.code),) + e[1:])
75 self.data[i] = type(e)((label(e.code),) + e[1:])
76 if e.calls:
76 if e.calls:
77 for j in range(len(e.calls)):
77 for j in range(len(e.calls)):
78 se = e.calls[j]
78 se = e.calls[j]
79 if not isinstance(se.code, str):
79 if not isinstance(se.code, str):
80 e.calls[j] = type(se)((label(se.code),) + se[1:])
80 e.calls[j] = type(se)((label(se.code),) + se[1:])
81
81
82 _fn2mod = {}
82 _fn2mod = {}
83
83
84 def label(code):
84 def label(code):
85 if isinstance(code, str):
85 if isinstance(code, str):
86 return code
86 return code
87 try:
87 try:
88 mname = _fn2mod[code.co_filename]
88 mname = _fn2mod[code.co_filename]
89 except KeyError:
89 except KeyError:
90 for k, v in sys.modules.iteritems():
90 for k, v in list(sys.modules.iteritems()):
91 if v is None:
91 if v is None:
92 continue
92 continue
93 if not hasattr(v, '__file__'):
93 if not hasattr(v, '__file__'):
94 continue
94 continue
95 if not isinstance(v.__file__, str):
95 if not isinstance(v.__file__, str):
96 continue
96 continue
97 if v.__file__.startswith(code.co_filename):
97 if v.__file__.startswith(code.co_filename):
98 mname = _fn2mod[code.co_filename] = k
98 mname = _fn2mod[code.co_filename] = k
99 break
99 break
100 else:
100 else:
101 mname = _fn2mod[code.co_filename] = '<%s>'%code.co_filename
101 mname = _fn2mod[code.co_filename] = '<%s>'%code.co_filename
102
102
103 return '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name)
103 return '%s:%d(%s)' % (mname, code.co_firstlineno, code.co_name)
104
104
105
105
106 if __name__ == '__main__':
106 if __name__ == '__main__':
107 import os
107 import os
108 sys.argv = sys.argv[1:]
108 sys.argv = sys.argv[1:]
109 if not sys.argv:
109 if not sys.argv:
110 print >> sys.stderr, "usage: lsprof.py <script> <arguments...>"
110 print >> sys.stderr, "usage: lsprof.py <script> <arguments...>"
111 sys.exit(2)
111 sys.exit(2)
112 sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])))
112 sys.path.insert(0, os.path.abspath(os.path.dirname(sys.argv[0])))
113 stats = profile(execfile, sys.argv[0], globals(), locals())
113 stats = profile(execfile, sys.argv[0], globals(), locals())
114 stats.sort()
114 stats.sort()
115 stats.pprint()
115 stats.pprint()
General Comments 0
You need to be logged in to leave comments. Login now