annotate mercurial/statprof.py @ 38618:c829749e7639

shelve: directly handle the initial parent alignment Shelve is currently sub-contracting some of its work to the rebase extension. In order to make shelve more independent and flexible we would like shelve to handle the parent alignment directly. After this change, we no longer need to use rebase in shelve. Differential Revision: https://phab.mercurial-scm.org/D3693
author Boris Feld <boris.feld@octobus.net>
date Tue, 29 May 2018 00:30:50 +0200
parents 99188a7c8717
children 3c569172848d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 #!/usr/bin/env python
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 ## statprof.py
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 ## Copyright (C) 2012 Bryan O'Sullivan <bos@serpentine.com>
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 ## Copyright (C) 2011 Alex Fraser <alex at phatcore dot com>
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 ## Copyright (C) 2004,2005 Andy Wingo <wingo at pobox dot com>
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 ## Copyright (C) 2001 Rob Browning <rlb at defaultvalue dot org>
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 ## This library is free software; you can redistribute it and/or
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9 ## modify it under the terms of the GNU Lesser General Public
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
10 ## License as published by the Free Software Foundation; either
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
11 ## version 2.1 of the License, or (at your option) any later version.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12 ##
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13 ## This library is distributed in the hope that it will be useful,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
15 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
16 ## Lesser General Public License for more details.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
17 ##
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18 ## You should have received a copy of the GNU Lesser General Public
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
19 ## License along with this program; if not, contact:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
20 ##
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
21 ## Free Software Foundation Voice: +1-617-542-5942
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
22 ## 59 Temple Place - Suite 330 Fax: +1-617-542-2652
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
23 ## Boston, MA 02111-1307, USA gnu@gnu.org
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
24
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25 """
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
26 statprof is intended to be a fairly simple statistical profiler for
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
27 python. It was ported directly from a statistical profiler for guile,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
28 also named statprof, available from guile-lib [0].
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
29
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
30 [0] http://wingolog.org/software/guile-lib/statprof/
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
31
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
32 To start profiling, call statprof.start():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
33 >>> start()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
34
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
35 Then run whatever it is that you want to profile, for example:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
36 >>> import test.pystone; test.pystone.pystones()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
37
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
38 Then stop the profiling and print out the results:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
39 >>> stop()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
40 >>> display()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
41 % cumulative self
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
42 time seconds seconds name
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
43 26.72 1.40 0.37 pystone.py:79:Proc0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
44 13.79 0.56 0.19 pystone.py:133:Proc1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
45 13.79 0.19 0.19 pystone.py:208:Proc8
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
46 10.34 0.16 0.14 pystone.py:229:Func2
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
47 6.90 0.10 0.10 pystone.py:45:__init__
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
48 4.31 0.16 0.06 pystone.py:53:copy
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
49 ...
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
50
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
51 All of the numerical data is statistically approximate. In the
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
52 following column descriptions, and in all of statprof, "time" refers
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
53 to execution time (both user and system), not wall clock time.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
54
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55 % time
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
56 The percent of the time spent inside the procedure itself (not
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
57 counting children).
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
58
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
59 cumulative seconds
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
60 The total number of seconds spent in the procedure, including
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
61 children.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
62
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
63 self seconds
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64 The total number of seconds spent in the procedure itself (not
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65 counting children).
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
66
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 name
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
68 The name of the procedure.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 By default statprof keeps the data collected from previous runs. If you
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 want to clear the collected data, call reset():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
72 >>> reset()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
73
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
74 reset() can also be used to change the sampling frequency from the
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75 default of 1000 Hz. For example, to tell statprof to sample 50 times a
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
76 second:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
77 >>> reset(50)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
78
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
79 This means that statprof will sample the call stack after every 1/50 of
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
80 a second of user + system time spent running on behalf of the python
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
81 process. When your process is idle (for example, blocking in a read(),
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
82 as is the case at the listener), the clock does not advance. For this
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
83 reason statprof is not currently not suitable for profiling io-bound
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
84 operations.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
85
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
86 The profiler uses the hash of the code object itself to identify the
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
87 procedures, so it won't confuse different procedures with the same name.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
88 They will show up as two different rows in the output.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
89
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
90 Right now the profiler is quite simplistic. I cannot provide
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
91 call-graphs or other higher level information. What you see in the
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
92 table is pretty much all there is. Patches are welcome :-)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
93
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
94
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
95 Threading
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
96 ---------
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
97
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
98 Because signals only get delivered to the main thread in Python,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
99 statprof only profiles the main thread. However because the time
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
100 reporting function uses per-process timers, the results can be
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
101 significantly off if other threads' work patterns are not similar to the
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
102 main thread's work patterns.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
103 """
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
104 # no-check-code
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
105 from __future__ import absolute_import, division, print_function
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
106
30256
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
107 import collections
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
108 import contextlib
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
109 import getopt
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
110 import inspect
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
111 import json
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
112 import os
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
113 import signal
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
114 import sys
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
115 import threading
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
116 import time
30256
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
117
30578
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30568
diff changeset
118 from . import (
30637
344e68882cd3 py3: replace os.environ with encoding.environ (part 4 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30578
diff changeset
119 encoding,
30578
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30568
diff changeset
120 pycompat,
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30568
diff changeset
121 )
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30568
diff changeset
122
30256
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
123 defaultdict = collections.defaultdict
2ed0b3f9f79e statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30255
diff changeset
124 contextmanager = contextlib.contextmanager
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
125
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
126 __all__ = ['start', 'stop', 'reset', 'display', 'profile']
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
127
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
128 skips = {"util.py:check", "extensions.py:closure",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
129 "color.py:colorcmd", "dispatch.py:checkargs",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
130 "dispatch.py:<lambda>", "dispatch.py:_runcatch",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
131 "dispatch.py:_dispatch", "dispatch.py:_runcommand",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
132 "pager.py:pagecmd", "dispatch.py:run",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
133 "dispatch.py:dispatch", "dispatch.py:runcommand",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
134 "hg.py:<module>", "evolve.py:warnobserrors",
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 31074
diff changeset
135 }
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
136
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
137 ###########################################################################
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
138 ## Utils
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
139
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
140 def clock():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
141 times = os.times()
38259
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
142 return (times[0] + times[1], times[4])
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
143
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
144
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
145 ###########################################################################
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
146 ## Collection data structures
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
147
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
148 class ProfileState(object):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
149 def __init__(self, frequency=None):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
150 self.reset(frequency)
38260
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
151 self.track = 'cpu'
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
152
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
153 def reset(self, frequency=None):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
154 # total so far
38259
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
155 self.accumulated_time = (0.0, 0.0)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
156 # start_time when timer is active
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
157 self.last_start_time = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
158 # a float
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
159 if frequency:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
160 self.sample_interval = 1.0 / frequency
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
161 elif not hasattr(self, 'sample_interval'):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
162 # default to 1000 Hz
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
163 self.sample_interval = 1.0 / 1000.0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
164 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
165 # leave the frequency as it was
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
166 pass
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
167 self.remaining_prof_time = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
168 # for user start/stop nesting
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
169 self.profile_level = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
170
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
171 self.samples = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
172
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
173 def accumulate_time(self, stop_time):
38259
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
174 increment = (
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
175 stop_time[0] - self.last_start_time[0],
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
176 stop_time[1] - self.last_start_time[1],
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
177 )
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
178 self.accumulated_time = (
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
179 self.accumulated_time[0] + increment[0],
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
180 self.accumulated_time[1] + increment[1],
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
181 )
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
182
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
183 def seconds_per_sample(self):
38260
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
184 return self.accumulated_time[self.timeidx] / len(self.samples)
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
185
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
186 @property
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
187 def timeidx(self):
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
188 if self.track == 'real':
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
189 return 1
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
190 return 0
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
191
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
192 state = ProfileState()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
193
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
194
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
195 class CodeSite(object):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
196 cache = {}
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
197
30568
bb35fe8621f5 py3: use unicodes in __slots__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30299
diff changeset
198 __slots__ = (u'path', u'lineno', u'function', u'source')
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
199
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
200 def __init__(self, path, lineno, function):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
201 self.path = path
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
202 self.lineno = lineno
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
203 self.function = function
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
204 self.source = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
205
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
206 def __eq__(self, other):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
207 try:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
208 return (self.lineno == other.lineno and
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
209 self.path == other.path)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
210 except:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
211 return False
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
212
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
213 def __hash__(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
214 return hash((self.lineno, self.path))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
215
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
216 @classmethod
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
217 def get(cls, path, lineno, function):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
218 k = (path, lineno)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
219 try:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
220 return cls.cache[k]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
221 except KeyError:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
222 v = cls(path, lineno, function)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
223 cls.cache[k] = v
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
224 return v
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
225
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
226 def getsource(self, length):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
227 if self.source is None:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
228 lineno = self.lineno - 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
229 fp = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
230 try:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
231 fp = open(self.path)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
232 for i, line in enumerate(fp):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
233 if i == lineno:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
234 self.source = line.strip()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
235 break
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
236 except:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
237 pass
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
238 finally:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
239 if fp:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
240 fp.close()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
241 if self.source is None:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
242 self.source = ''
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
243
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
244 source = self.source
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
245 if len(source) > length:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
246 source = source[:(length - 3)] + "..."
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
247 return source
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
248
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
249 def filename(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
250 return os.path.basename(self.path)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
251
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
252 class Sample(object):
30568
bb35fe8621f5 py3: use unicodes in __slots__
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30299
diff changeset
253 __slots__ = (u'stack', u'time')
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
254
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
255 def __init__(self, stack, time):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
256 self.stack = stack
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
257 self.time = time
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
258
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
259 @classmethod
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
260 def from_frame(cls, frame, time):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
261 stack = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
262
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
263 while frame:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
264 stack.append(CodeSite.get(frame.f_code.co_filename, frame.f_lineno,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
265 frame.f_code.co_name))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
266 frame = frame.f_back
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
267
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
268 return Sample(stack, time)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
269
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
270 ###########################################################################
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
271 ## SIGPROF handler
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
272
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
273 def profile_signal_handler(signum, frame):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
274 if state.profile_level > 0:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
275 now = clock()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
276 state.accumulate_time(now)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
277
38260
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
278 timestamp = state.accumulated_time[state.timeidx]
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
279 state.samples.append(Sample.from_frame(frame, timestamp))
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
280
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
281 signal.setitimer(signal.ITIMER_PROF,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
282 state.sample_interval, 0.0)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
283 state.last_start_time = now
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
284
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
285 stopthread = threading.Event()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
286 def samplerthread(tid):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
287 while not stopthread.is_set():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
288 now = clock()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
289 state.accumulate_time(now)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
290
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
291 frame = sys._current_frames()[tid]
38260
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
292
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
293 timestamp = state.accumulated_time[state.timeidx]
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
294 state.samples.append(Sample.from_frame(frame, timestamp))
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
295
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
296 state.last_start_time = now
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
297 time.sleep(state.sample_interval)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
298
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
299 stopthread.clear()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
300
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
301 ###########################################################################
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
302 ## Profiling API
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
303
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
304 def is_active():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
305 return state.profile_level > 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
306
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
307 lastmechanism = None
38260
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
308 def start(mechanism='thread', track='cpu'):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
309 '''Install the profiling signal handler, and start profiling.'''
38260
15a1e37f80bd profiling: introduce a "profiling.time-track" option
Boris Feld <boris.feld@octobus.net>
parents: 38259
diff changeset
310 state.track = track # note: nesting different mode won't work
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
311 state.profile_level += 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
312 if state.profile_level == 1:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
313 state.last_start_time = clock()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
314 rpt = state.remaining_prof_time
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
315 state.remaining_prof_time = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
316
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
317 global lastmechanism
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
318 lastmechanism = mechanism
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
319
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
320 if mechanism == 'signal':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
321 signal.signal(signal.SIGPROF, profile_signal_handler)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
322 signal.setitimer(signal.ITIMER_PROF,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
323 rpt or state.sample_interval, 0.0)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
324 elif mechanism == 'thread':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
325 frame = inspect.currentframe()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
326 tid = [k for k, f in sys._current_frames().items() if f == frame][0]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
327 state.thread = threading.Thread(target=samplerthread,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
328 args=(tid,), name="samplerthread")
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
329 state.thread.start()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
330
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
331 def stop():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
332 '''Stop profiling, and uninstall the profiling signal handler.'''
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
333 state.profile_level -= 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
334 if state.profile_level == 0:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
335 if lastmechanism == 'signal':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
336 rpt = signal.setitimer(signal.ITIMER_PROF, 0.0, 0.0)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
337 signal.signal(signal.SIGPROF, signal.SIG_IGN)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
338 state.remaining_prof_time = rpt[0]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
339 elif lastmechanism == 'thread':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
340 stopthread.set()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
341 state.thread.join()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
342
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
343 state.accumulate_time(clock())
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
344 state.last_start_time = None
30637
344e68882cd3 py3: replace os.environ with encoding.environ (part 4 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30578
diff changeset
345 statprofpath = encoding.environ.get('STATPROF_DEST')
30255
f42cd5434cc2 statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30254
diff changeset
346 if statprofpath:
f42cd5434cc2 statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30254
diff changeset
347 save_data(statprofpath)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
348
30299
1e5346313963 statprof: return state from stop()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30258
diff changeset
349 return state
1e5346313963 statprof: return state from stop()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30258
diff changeset
350
30255
f42cd5434cc2 statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30254
diff changeset
351 def save_data(path):
f42cd5434cc2 statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30254
diff changeset
352 with open(path, 'w+') as file:
38274
99188a7c8717 statprof: fix save and load
Boris Feld <boris.feld@octobus.net>
parents: 38260
diff changeset
353 file.write("%f %f\n" % state.accumulated_time)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
354 for sample in state.samples:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
355 time = str(sample.time)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
356 stack = sample.stack
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
357 sites = ['\1'.join([s.path, str(s.lineno), s.function])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
358 for s in stack]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
359 file.write(time + '\0' + '\0'.join(sites) + '\n')
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
360
30255
f42cd5434cc2 statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30254
diff changeset
361 def load_data(path):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
362 lines = open(path, 'r').read().splitlines()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
363
38274
99188a7c8717 statprof: fix save and load
Boris Feld <boris.feld@octobus.net>
parents: 38260
diff changeset
364 state.accumulated_time = [float(value) for value in lines[0].split()]
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
365 state.samples = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
366 for line in lines[1:]:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
367 parts = line.split('\0')
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
368 time = float(parts[0])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
369 rawsites = parts[1:]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
370 sites = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
371 for rawsite in rawsites:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
372 siteparts = rawsite.split('\1')
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
373 sites.append(CodeSite.get(siteparts[0], int(siteparts[1]),
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
374 siteparts[2]))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
375
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
376 state.samples.append(Sample(sites, time))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
377
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
378
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
379
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
380 def reset(frequency=None):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
381 '''Clear out the state of the profiler. Do not call while the
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
382 profiler is running.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
383
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
384 The optional frequency argument specifies the number of samples to
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
385 collect per second.'''
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
386 assert state.profile_level == 0, "Can't reset() while statprof is running"
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
387 CodeSite.cache.clear()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
388 state.reset(frequency)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
389
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
390
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
391 @contextmanager
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
392 def profile():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
393 start()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
394 try:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
395 yield
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
396 finally:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
397 stop()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
398 display()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
399
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
400
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
401 ###########################################################################
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
402 ## Reporting API
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
403
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
404 class SiteStats(object):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
405 def __init__(self, site):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
406 self.site = site
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
407 self.selfcount = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
408 self.totalcount = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
409
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
410 def addself(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
411 self.selfcount += 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
412
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
413 def addtotal(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
414 self.totalcount += 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
415
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
416 def selfpercent(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
417 return self.selfcount / len(state.samples) * 100
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
418
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
419 def totalpercent(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
420 return self.totalcount / len(state.samples) * 100
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
421
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
422 def selfseconds(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
423 return self.selfcount * state.seconds_per_sample()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
424
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
425 def totalseconds(self):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
426 return self.totalcount * state.seconds_per_sample()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
427
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
428 @classmethod
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
429 def buildstats(cls, samples):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
430 stats = {}
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
431
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
432 for sample in samples:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
433 for i, site in enumerate(sample.stack):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
434 sitestat = stats.get(site)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
435 if not sitestat:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
436 sitestat = SiteStats(site)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
437 stats[site] = sitestat
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
438
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
439 sitestat.addtotal()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
440
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
441 if i == 0:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
442 sitestat.addself()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
443
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
444 return [s for s in stats.itervalues()]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
445
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
446 class DisplayFormats:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
447 ByLine = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
448 ByMethod = 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
449 AboutMethod = 2
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
450 Hotpath = 3
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
451 FlameGraph = 4
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
452 Json = 5
30929
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
453 Chrome = 6
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
454
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
455 def display(fp=None, format=3, data=None, **kwargs):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
456 '''Print statistics, either to stdout or the given file object.'''
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
457 data = data or state
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
458
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
459 if fp is None:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
460 import sys
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
461 fp = sys.stdout
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
462 if len(data.samples) == 0:
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
463 print('No samples recorded.', file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
464 return
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
465
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
466 if format == DisplayFormats.ByLine:
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
467 display_by_line(data, fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
468 elif format == DisplayFormats.ByMethod:
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
469 display_by_method(data, fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
470 elif format == DisplayFormats.AboutMethod:
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
471 display_about_method(data, fp, **kwargs)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
472 elif format == DisplayFormats.Hotpath:
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
473 display_hotpath(data, fp, **kwargs)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
474 elif format == DisplayFormats.FlameGraph:
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
475 write_to_flame(data, fp, **kwargs)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
476 elif format == DisplayFormats.Json:
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
477 write_to_json(data, fp)
30929
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
478 elif format == DisplayFormats.Chrome:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
479 write_to_chrome(data, fp, **kwargs)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
480 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
481 raise Exception("Invalid display format")
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
482
30929
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
483 if format not in (DisplayFormats.Json, DisplayFormats.Chrome):
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
484 print('---', file=fp)
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
485 print('Sample count: %d' % len(data.samples), file=fp)
38259
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
486 print('Total time: %f seconds (%f wall)' % data.accumulated_time,
af402c6b90db statprof: also gather wall time
Boris Feld <boris.feld@octobus.net>
parents: 38164
diff changeset
487 file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
488
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
489 def display_by_line(data, fp):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
490 '''Print the profiler data with each sample line represented
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
491 as one row in a table. Sorted by self-time per line.'''
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
492 stats = SiteStats.buildstats(data.samples)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
493 stats.sort(reverse=True, key=lambda x: x.selfseconds())
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
494
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
495 print('%5.5s %10.10s %7.7s %-8.8s' %
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
496 ('% ', 'cumulative', 'self', ''), file=fp)
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
497 print('%5.5s %9.9s %8.8s %-8.8s' %
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
498 ("time", "seconds", "seconds", "name"), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
499
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
500 for stat in stats:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
501 site = stat.site
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
502 sitelabel = '%s:%d:%s' % (site.filename(), site.lineno, site.function)
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
503 print('%6.2f %9.2f %9.2f %s' % (stat.selfpercent(),
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
504 stat.totalseconds(),
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
505 stat.selfseconds(),
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
506 sitelabel),
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
507 file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
508
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
509 def display_by_method(data, fp):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
510 '''Print the profiler data with each sample function represented
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
511 as one row in a table. Important lines within that function are
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
512 output as nested rows. Sorted by self-time per line.'''
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
513 print('%5.5s %10.10s %7.7s %-8.8s' %
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
514 ('% ', 'cumulative', 'self', ''), file=fp)
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
515 print('%5.5s %9.9s %8.8s %-8.8s' %
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
516 ("time", "seconds", "seconds", "name"), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
517
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
518 stats = SiteStats.buildstats(data.samples)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
519
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
520 grouped = defaultdict(list)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
521 for stat in stats:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
522 grouped[stat.site.filename() + ":" + stat.site.function].append(stat)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
523
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
524 # compute sums for each function
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
525 functiondata = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
526 for fname, sitestats in grouped.iteritems():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
527 total_cum_sec = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
528 total_self_sec = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
529 total_percent = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
530 for stat in sitestats:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
531 total_cum_sec += stat.totalseconds()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
532 total_self_sec += stat.selfseconds()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
533 total_percent += stat.selfpercent()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
534
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
535 functiondata.append((fname,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
536 total_cum_sec,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
537 total_self_sec,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
538 total_percent,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
539 sitestats))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
540
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
541 # sort by total self sec
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
542 functiondata.sort(reverse=True, key=lambda x: x[2])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
543
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
544 for function in functiondata:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
545 if function[3] < 0.05:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
546 continue
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
547 print('%6.2f %9.2f %9.2f %s' % (function[3], # total percent
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
548 function[1], # total cum sec
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
549 function[2], # total self sec
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
550 function[0]), # file:function
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
551 file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
552 function[4].sort(reverse=True, key=lambda i: i.selfseconds())
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
553 for stat in function[4]:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
554 # only show line numbers for significant locations (>1% time spent)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
555 if stat.selfpercent() > 1:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
556 source = stat.site.getsource(25)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
557 stattuple = (stat.selfpercent(), stat.selfseconds(),
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
558 stat.site.lineno, source)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
559
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
560 print('%33.0f%% %6.2f line %s: %s' % (stattuple), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
561
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
562 def display_about_method(data, fp, function=None, **kwargs):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
563 if function is None:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
564 raise Exception("Invalid function")
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
565
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
566 filename = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
567 if ':' in function:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
568 filename, function = function.split(':')
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
569
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
570 relevant_samples = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
571 parents = {}
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
572 children = {}
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
573
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
574 for sample in data.samples:
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
575 for i, site in enumerate(sample.stack):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
576 if site.function == function and (not filename
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
577 or site.filename() == filename):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
578 relevant_samples += 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
579 if i != len(sample.stack) - 1:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
580 parent = sample.stack[i + 1]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
581 if parent in parents:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
582 parents[parent] = parents[parent] + 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
583 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
584 parents[parent] = 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
585
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
586 if site in children:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
587 children[site] = children[site] + 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
588 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
589 children[site] = 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
590
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
591 parents = [(parent, count) for parent, count in parents.iteritems()]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
592 parents.sort(reverse=True, key=lambda x: x[1])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
593 for parent, count in parents:
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
594 print('%6.2f%% %s:%s line %s: %s' %
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
595 (count / relevant_samples * 100, parent.filename(),
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
596 parent.function, parent.lineno, parent.getsource(50)), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
597
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
598 stats = SiteStats.buildstats(data.samples)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
599 stats = [s for s in stats
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
600 if s.site.function == function and
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
601 (not filename or s.site.filename() == filename)]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
602
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
603 total_cum_sec = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
604 total_self_sec = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
605 total_self_percent = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
606 total_cum_percent = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
607 for stat in stats:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
608 total_cum_sec += stat.totalseconds()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
609 total_self_sec += stat.selfseconds()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
610 total_self_percent += stat.selfpercent()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
611 total_cum_percent += stat.totalpercent()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
612
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
613 print(
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
614 '\n %s:%s Total: %0.2fs (%0.2f%%) Self: %0.2fs (%0.2f%%)\n' %
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
615 (
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
616 filename or '___',
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
617 function,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
618 total_cum_sec,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
619 total_cum_percent,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
620 total_self_sec,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
621 total_self_percent
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
622 ), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
623
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
624 children = [(child, count) for child, count in children.iteritems()]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
625 children.sort(reverse=True, key=lambda x: x[1])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
626 for child, count in children:
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
627 print(' %6.2f%% line %s: %s' %
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
628 (count / relevant_samples * 100, child.lineno,
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
629 child.getsource(50)), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
630
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
631 def display_hotpath(data, fp, limit=0.05, **kwargs):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
632 class HotNode(object):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
633 def __init__(self, site):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
634 self.site = site
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
635 self.count = 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
636 self.children = {}
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
637
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
638 def add(self, stack, time):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
639 self.count += time
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
640 site = stack[0]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
641 child = self.children.get(site)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
642 if not child:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
643 child = HotNode(site)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
644 self.children[site] = child
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
645
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
646 if len(stack) > 1:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
647 i = 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
648 # Skip boiler plate parts of the stack
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
649 while i < len(stack) and '%s:%s' % (stack[i].filename(), stack[i].function) in skips:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
650 i += 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
651 if i < len(stack):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
652 child.add(stack[i:], time)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
653
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
654 root = HotNode(None)
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
655 lasttime = data.samples[0].time
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
656 for sample in data.samples:
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
657 root.add(sample.stack[::-1], sample.time - lasttime)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
658 lasttime = sample.time
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
659
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
660 def _write(node, depth, multiple_siblings):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
661 site = node.site
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
662 visiblechildren = [c for c in node.children.itervalues()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
663 if c.count >= (limit * root.count)]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
664 if site:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
665 indent = depth * 2 - 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
666 filename = ''
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
667 function = ''
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
668 if len(node.children) > 0:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
669 childsite = list(node.children.itervalues())[0].site
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
670 filename = (childsite.filename() + ':').ljust(15)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
671 function = childsite.function
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
672
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
673 # lots of string formatting
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
674 listpattern = ''.ljust(indent) +\
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
675 ('\\' if multiple_siblings else '|') +\
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
676 ' %4.1f%% %s %s'
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
677 liststring = listpattern % (node.count / root.count * 100,
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
678 filename, function)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
679 codepattern = '%' + str(55 - len(liststring)) + 's %s: %s'
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
680 codestring = codepattern % ('line', site.lineno, site.getsource(30))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
681
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
682 finalstring = liststring + codestring
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
683 childrensamples = sum([c.count for c in node.children.itervalues()])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
684 # Make frames that performed more than 10% of the operation red
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
685 if node.count - childrensamples > (0.1 * root.count):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
686 finalstring = '\033[91m' + finalstring + '\033[0m'
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
687 # Make frames that didn't actually perform work dark grey
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
688 elif node.count - childrensamples == 0:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
689 finalstring = '\033[90m' + finalstring + '\033[0m'
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
690 print(finalstring, file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
691
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
692 newdepth = depth
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
693 if len(visiblechildren) > 1 or multiple_siblings:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
694 newdepth += 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
695
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
696 visiblechildren.sort(reverse=True, key=lambda x: x.count)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
697 for child in visiblechildren:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
698 _write(child, newdepth, len(visiblechildren) > 1)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
699
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
700 if root.count > 0:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
701 _write(root, 0, False)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
702
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
703 def write_to_flame(data, fp, scriptpath=None, outputfile=None, **kwargs):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
704 if scriptpath is None:
30637
344e68882cd3 py3: replace os.environ with encoding.environ (part 4 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30578
diff changeset
705 scriptpath = encoding.environ['HOME'] + '/flamegraph.pl'
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
706 if not os.path.exists(scriptpath):
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
707 print("error: missing %s" % scriptpath, file=fp)
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
708 print("get it here: https://github.com/brendangregg/FlameGraph",
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
709 file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
710 return
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
711
38164
aac4be30e250 py3: wrap tempfile.mkstemp() to use bytes path
Yuya Nishihara <yuya@tcha.org>
parents: 35413
diff changeset
712 fd, path = pycompat.mkstemp()
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
713
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
714 file = open(path, "w+")
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
715
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
716 lines = {}
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
717 for sample in data.samples:
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
718 sites = [s.function for s in sample.stack]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
719 sites.reverse()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
720 line = ';'.join(sites)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
721 if line in lines:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
722 lines[line] = lines[line] + 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
723 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
724 lines[line] = 1
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
725
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
726 for line, count in lines.iteritems():
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
727 file.write("%s %s\n" % (line, count))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
728
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
729 file.close()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
730
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
731 if outputfile is None:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
732 outputfile = '~/flamegraph.svg'
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
733
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
734 os.system("perl ~/flamegraph.pl %s > %s" % (path, outputfile))
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
735 print("Written to %s" % outputfile, file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
736
30928
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
737 _pathcache = {}
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
738 def simplifypath(path):
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
739 '''Attempt to make the path to a Python module easier to read by
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
740 removing whatever part of the Python search path it was found
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
741 on.'''
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
742
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
743 if path in _pathcache:
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
744 return _pathcache[path]
31074
2912b06905dc py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30929
diff changeset
745 hgpath = pycompat.fsencode(encoding.__file__).rsplit(os.sep, 2)[0]
30928
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
746 for p in [hgpath] + sys.path:
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
747 prefix = p + os.sep
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
748 if path.startswith(prefix):
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
749 path = path[len(prefix):]
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
750 break
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
751 _pathcache[path] = path
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
752 return path
be3a4fde38eb statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents: 30845
diff changeset
753
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
754 def write_to_json(data, fp):
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
755 samples = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
756
30258
eea89068a98d statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30257
diff changeset
757 for sample in data.samples:
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
758 stack = []
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
759
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
760 for frame in sample.stack:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
761 stack.append((frame.path, frame.lineno, frame.function))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
762
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
763 samples.append((sample.time, stack))
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
764
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
765 print(json.dumps(samples), file=fp)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
766
30929
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
767 def write_to_chrome(data, fp, minthreshold=0.005, maxthreshold=0.999):
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
768 samples = []
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
769 laststack = collections.deque()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
770 lastseen = collections.deque()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
771
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
772 # The Chrome tracing format allows us to use a compact stack
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
773 # representation to save space. It's fiddly but worth it.
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
774 # We maintain a bijection between stack and ID.
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
775 stack2id = {}
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
776 id2stack = [] # will eventually be rendered
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
777
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
778 def stackid(stack):
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
779 if not stack:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
780 return
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
781 if stack in stack2id:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
782 return stack2id[stack]
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
783 parent = stackid(stack[1:])
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
784 myid = len(stack2id)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
785 stack2id[stack] = myid
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
786 id2stack.append(dict(category=stack[0][0], name='%s %s' % stack[0]))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
787 if parent is not None:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
788 id2stack[-1].update(parent=parent)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
789 return myid
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
790
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
791 def endswith(a, b):
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
792 return list(a)[-len(b):] == list(b)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
793
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
794 # The sampling profiler can sample multiple times without
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
795 # advancing the clock, potentially causing the Chrome trace viewer
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
796 # to render single-pixel columns that we cannot zoom in on. We
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
797 # work around this by pretending that zero-duration samples are a
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
798 # millisecond in length.
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
799
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
800 clamp = 0.001
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
801
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
802 # We provide knobs that by default attempt to filter out stack
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
803 # frames that are too noisy:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
804 #
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
805 # * A few take almost all execution time. These are usually boring
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
806 # setup functions, giving a stack that is deep but uninformative.
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
807 #
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
808 # * Numerous samples take almost no time, but introduce lots of
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
809 # noisy, oft-deep "spines" into a rendered profile.
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
810
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
811 blacklist = set()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
812 totaltime = data.samples[-1].time - data.samples[0].time
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
813 minthreshold = totaltime * minthreshold
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
814 maxthreshold = max(totaltime * maxthreshold, clamp)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
815
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
816 def poplast():
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
817 oldsid = stackid(tuple(laststack))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
818 oldcat, oldfunc = laststack.popleft()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
819 oldtime, oldidx = lastseen.popleft()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
820 duration = sample.time - oldtime
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
821 if minthreshold <= duration <= maxthreshold:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
822 # ensure no zero-duration events
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
823 sampletime = max(oldtime + clamp, sample.time)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
824 samples.append(dict(ph='E', name=oldfunc, cat=oldcat, sf=oldsid,
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
825 ts=sampletime*1e6, pid=0))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
826 else:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
827 blacklist.add(oldidx)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
828
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
829 # Much fiddling to synthesize correctly(ish) nested begin/end
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
830 # events given only stack snapshots.
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
831
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
832 for sample in data.samples:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
833 tos = sample.stack[0]
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
834 name = tos.function
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
835 path = simplifypath(tos.path)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
836 stack = tuple((('%s:%d' % (simplifypath(frame.path), frame.lineno),
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
837 frame.function) for frame in sample.stack))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
838 qstack = collections.deque(stack)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
839 if laststack == qstack:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
840 continue
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
841 while laststack and qstack and laststack[-1] == qstack[-1]:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
842 laststack.pop()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
843 qstack.pop()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
844 while laststack:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
845 poplast()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
846 for f in reversed(qstack):
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
847 lastseen.appendleft((sample.time, len(samples)))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
848 laststack.appendleft(f)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
849 path, name = f
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
850 sid = stackid(tuple(laststack))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
851 samples.append(dict(ph='B', name=name, cat=path, ts=sample.time*1e6,
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
852 sf=sid, pid=0))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
853 laststack = collections.deque(stack)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
854 while laststack:
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
855 poplast()
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
856 events = [s[1] for s in enumerate(samples) if s[0] not in blacklist]
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
857 frames = collections.OrderedDict((str(k), v)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
858 for (k,v) in enumerate(id2stack))
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
859 json.dump(dict(traceEvents=events, stackFrames=frames), fp, indent=1)
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
860 fp.write('\n')
cb440e7af05d statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents: 30928
diff changeset
861
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
862 def printusage():
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
863 print("""
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
864 The statprof command line allows you to inspect the last profile's results in
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
865 the following forms:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
866
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
867 usage:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
868 hotpath [-l --limit percent]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
869 Shows a graph of calls with the percent of time each takes.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
870 Red calls take over 10%% of the total time themselves.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
871 lines
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
872 Shows the actual sampled lines.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
873 functions
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
874 Shows the samples grouped by function.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
875 function [filename:]functionname
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
876 Shows the callers and callees of a particular function.
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
877 flame [-s --script-path] [-o --output-file path]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
878 Writes out a flamegraph to output-file (defaults to ~/flamegraph.svg)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
879 Requires that ~/flamegraph.pl exist.
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
880 (Specify alternate script path with --script-path.)""")
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
881
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
882 def main(argv=None):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
883 if argv is None:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
884 argv = sys.argv
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
885
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
886 if len(argv) == 1:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
887 printusage()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
888 return 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
889
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
890 displayargs = {}
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
891
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
892 optstart = 2
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
893 displayargs['function'] = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
894 if argv[1] == 'hotpath':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
895 displayargs['format'] = DisplayFormats.Hotpath
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
896 elif argv[1] == 'lines':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
897 displayargs['format'] = DisplayFormats.ByLine
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
898 elif argv[1] == 'functions':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
899 displayargs['format'] = DisplayFormats.ByMethod
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
900 elif argv[1] == 'function':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
901 displayargs['format'] = DisplayFormats.AboutMethod
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
902 displayargs['function'] = argv[2]
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
903 optstart = 3
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
904 elif argv[1] == 'flame':
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
905 displayargs['format'] = DisplayFormats.FlameGraph
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
906 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
907 printusage()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
908 return 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
909
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
910 # process options
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
911 try:
30578
c6ce11f2ee50 py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30568
diff changeset
912 opts, args = pycompat.getoptb(sys.argv[optstart:], "hl:f:o:p:",
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
913 ["help", "limit=", "file=", "output-file=", "script-path="])
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
914 except getopt.error as msg:
30257
7428223ed7c2 statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30256
diff changeset
915 print(msg)
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
916 printusage()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
917 return 2
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
918
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
919 displayargs['limit'] = 0.05
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
920 path = None
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
921 for o, value in opts:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
922 if o in ("-l", "--limit"):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
923 displayargs['limit'] = float(value)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
924 elif o in ("-f", "--file"):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
925 path = value
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
926 elif o in ("-o", "--output-file"):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
927 displayargs['outputfile'] = value
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
928 elif o in ("-p", "--script-path"):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
929 displayargs['scriptpath'] = value
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
930 elif o in ("-h", "help"):
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
931 printusage()
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
932 return 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
933 else:
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
934 assert False, "unhandled option %s" % o
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
935
30845
262c2be8ea5a statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30637
diff changeset
936 if not path:
262c2be8ea5a statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30637
diff changeset
937 print('must specify --file to load')
262c2be8ea5a statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30637
diff changeset
938 return 1
262c2be8ea5a statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30637
diff changeset
939
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
940 load_data(path=path)
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
941
35370
c5853c9a6545 py3: handle keyword arguments correctly in statprof.py
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32291
diff changeset
942 display(**pycompat.strkwargs(displayargs))
30253
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
943
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
944 return 0
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
945
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
946 if __name__ == "__main__":
b032a7b676c6 statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
947 sys.exit(main())