Mercurial > cpython-lru_cache-weakref
annotate Lib/cProfile.py @ 78069:a8aa77458e12 3.2
Add c_size_t and c_ssize_t to the ctypes summary table.
| author | Antoine Pitrou <solipsis@pitrou.net> |
|---|---|
| date | Thu, 12 Jul 2012 20:31:50 +0200 |
| parents | 3c9232a684ae |
| children | cb876235f29d |
| rev | line source |
|---|---|
|
59522
fcfe324663a6
convert shebang lines: python -> python3
Benjamin Peterson <benjamin@python.org>
parents:
55833
diff
changeset
|
1 #! /usr/bin/env python3 |
| 36459 | 2 |
| 3 """Python interface for the 'lsprof' profiler. | |
| 4 Compatible with the 'profile' module. | |
| 5 """ | |
| 6 | |
|
55833
4ddc0598df79
Remove the just-removed "help" from __all__.
Georg Brandl <georg@python.org>
parents:
55818
diff
changeset
|
7 __all__ = ["run", "runctx", "Profile"] |
| 36459 | 8 |
| 9 import _lsprof | |
| 10 | |
| 11 # ____________________________________________________________ | |
| 12 # Simple interface | |
| 13 | |
| 14 def run(statement, filename=None, sort=-1): | |
| 15 """Run statement under profiler optionally saving results in filename | |
| 16 | |
| 17 This function takes a single argument that can be passed to the | |
| 18 "exec" statement, and an optional file name. In all cases this | |
| 19 routine attempts to "exec" its first argument and gather profiling | |
| 20 statistics from the execution. If no file name is present, then this | |
| 21 function automatically prints a simple profiling report, sorted by the | |
| 22 standard name string (file/line/function-name) that is presented in | |
| 23 each line. | |
| 24 """ | |
| 25 prof = Profile() | |
| 26 result = None | |
| 27 try: | |
| 28 try: | |
| 29 prof = prof.run(statement) | |
| 30 except SystemExit: | |
| 31 pass | |
| 32 finally: | |
| 33 if filename is not None: | |
| 34 prof.dump_stats(filename) | |
| 35 else: | |
| 36 result = prof.print_stats(sort) | |
| 37 return result | |
| 38 | |
|
65115
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
39 def runctx(statement, globals, locals, filename=None, sort=-1): |
| 36459 | 40 """Run statement under profiler, supplying your own globals and locals, |
| 41 optionally saving results in filename. | |
| 42 | |
| 43 statement and filename have the same semantics as profile.run | |
| 44 """ | |
| 45 prof = Profile() | |
| 46 result = None | |
| 47 try: | |
| 48 try: | |
| 49 prof = prof.runctx(statement, globals, locals) | |
| 50 except SystemExit: | |
| 51 pass | |
| 52 finally: | |
| 53 if filename is not None: | |
| 54 prof.dump_stats(filename) | |
| 55 else: | |
|
65115
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
56 result = prof.print_stats(sort) |
| 36459 | 57 return result |
| 58 | |
| 59 # ____________________________________________________________ | |
| 60 | |
| 61 class Profile(_lsprof.Profiler): | |
| 62 """Profile(custom_timer=None, time_unit=None, subcalls=True, builtins=True) | |
| 63 | |
| 64 Builds a profiler object using the specified timer function. | |
| 65 The default timer is a fast built-in one based on real time. | |
| 66 For custom timer functions returning integers, time_unit can | |
| 67 be a float specifying a scale (i.e. how long each integer unit | |
| 68 is, in seconds). | |
| 69 """ | |
| 70 | |
| 71 # Most of the functionality is in the base class. | |
| 72 # This subclass only adds convenient and backward-compatible methods. | |
| 73 | |
| 74 def print_stats(self, sort=-1): | |
| 75 import pstats | |
| 76 pstats.Stats(self).strip_dirs().sort_stats(sort).print_stats() | |
| 77 | |
| 78 def dump_stats(self, file): | |
| 79 import marshal | |
| 80 f = open(file, 'wb') | |
| 81 self.create_stats() | |
| 82 marshal.dump(self.stats, f) | |
| 83 f.close() | |
| 84 | |
| 85 def create_stats(self): | |
| 86 self.disable() | |
| 87 self.snapshot_stats() | |
| 88 | |
| 89 def snapshot_stats(self): | |
| 90 entries = self.getstats() | |
| 91 self.stats = {} | |
| 92 callersdicts = {} | |
| 93 # call information | |
| 94 for entry in entries: | |
| 95 func = label(entry.code) | |
| 96 nc = entry.callcount # ncalls column of pstats (before '/') | |
| 97 cc = nc - entry.reccallcount # ncalls column of pstats (after '/') | |
| 98 tt = entry.inlinetime # tottime column of pstats | |
| 99 ct = entry.totaltime # cumtime column of pstats | |
| 100 callers = {} | |
| 101 callersdicts[id(entry.code)] = callers | |
| 102 self.stats[func] = cc, nc, tt, ct, callers | |
| 103 # subcall information | |
| 104 for entry in entries: | |
| 105 if entry.calls: | |
| 106 func = label(entry.code) | |
| 107 for subentry in entry.calls: | |
| 108 try: | |
| 109 callers = callersdicts[id(subentry.code)] | |
| 110 except KeyError: | |
| 111 continue | |
| 112 nc = subentry.callcount | |
| 113 cc = nc - subentry.reccallcount | |
| 114 tt = subentry.inlinetime | |
| 115 ct = subentry.totaltime | |
| 116 if func in callers: | |
| 117 prev = callers[func] | |
| 118 nc += prev[0] | |
| 119 cc += prev[1] | |
| 120 tt += prev[2] | |
| 121 ct += prev[3] | |
| 122 callers[func] = nc, cc, tt, ct | |
| 123 | |
| 124 # The following two methods can be called by clients to use | |
| 125 # a profiler to profile a statement, given as a string. | |
| 126 | |
| 127 def run(self, cmd): | |
| 128 import __main__ | |
| 129 dict = __main__.__dict__ | |
| 130 return self.runctx(cmd, dict, dict) | |
| 131 | |
| 132 def runctx(self, cmd, globals, locals): | |
| 133 self.enable() | |
| 134 try: | |
|
39782
c94f37054f19
Patch #1550800: make exec a function.
Georg Brandl <georg@python.org>
parents:
36459
diff
changeset
|
135 exec(cmd, globals, locals) |
| 36459 | 136 finally: |
| 137 self.disable() | |
| 138 return self | |
| 139 | |
| 140 # This method is more useful to profile a single function call. | |
| 141 def runcall(self, func, *args, **kw): | |
| 142 self.enable() | |
| 143 try: | |
| 144 return func(*args, **kw) | |
| 145 finally: | |
| 146 self.disable() | |
| 147 | |
| 148 # ____________________________________________________________ | |
| 149 | |
| 150 def label(code): | |
|
43577
ace45b361e87
Patch# 1258 by Christian Heimes: kill basestring.
Guido van Rossum <guido@python.org>
parents:
42552
diff
changeset
|
151 if isinstance(code, str): |
| 36459 | 152 return ('~', 0, code) # built-in functions ('~' sorts at the end) |
| 153 else: | |
| 154 return (code.co_filename, code.co_firstlineno, code.co_name) | |
| 155 | |
| 156 # ____________________________________________________________ | |
| 157 | |
| 158 def main(): | |
| 159 import os, sys | |
| 160 from optparse import OptionParser | |
| 161 usage = "cProfile.py [-o output_file_path] [-s sort] scriptfile [arg] ..." | |
| 162 parser = OptionParser(usage=usage) | |
| 163 parser.allow_interspersed_args = False | |
| 164 parser.add_option('-o', '--outfile', dest="outfile", | |
| 165 help="Save stats to <outfile>", default=None) | |
| 166 parser.add_option('-s', '--sort', dest="sort", | |
|
65115
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
167 help="Sort order when printing to stdout, based on pstats.Stats class", |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
168 default=-1) |
| 36459 | 169 |
| 170 if not sys.argv[1:]: | |
| 171 parser.print_usage() | |
| 172 sys.exit(2) | |
| 173 | |
| 174 (options, args) = parser.parse_args() | |
| 175 sys.argv[:] = args | |
| 176 | |
|
65115
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
177 if len(args) > 0: |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
178 progname = args[0] |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
179 sys.path.insert(0, os.path.dirname(progname)) |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
180 with open(progname, 'rb') as fp: |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
181 code = compile(fp.read(), progname, 'exec') |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
182 globs = { |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
183 '__file__': progname, |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
184 '__name__': '__main__', |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
185 '__package__': None, |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
186 '__cached__': None, |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
187 } |
|
b9a75dd7420d
Merged revisions 82805-82806,83523-83527,83536,83538,83542,83546-83548,83550-83555,83558,83560 via svnmerge from
Georg Brandl <georg@python.org>
parents:
43577
diff
changeset
|
188 runctx(code, globs, None, options.outfile, options.sort) |
| 36459 | 189 else: |
| 190 parser.print_usage() | |
| 191 return parser | |
| 192 | |
| 193 # When invoked as main program, invoke the profiler on a script | |
| 194 if __name__ == '__main__': | |
| 195 main() |
