Mercurial > hg
annotate mercurial/statprof.py @ 32228:112ba1c7d65d
perf: store reference to revlog._chunkraw in a local variable
To prepare for renaming revlog._chunkraw, we stuff a reference to this
metho in a local variable. This does 2 things. First, it moves the
attribute lookup outside of a loop, which more accurately measures
the time of the code being invoked. Second, it allows us to alias
to different methods depending on their presence (perf.py needs to
support running against old Mercurial versions).
Removing an attribute lookup from a tigh loop appears to shift the
numbers slightly with mozilla-central:
$ hg perfrevlogchunks -c
! read
! wall 0.354789 comb 0.340000 user 0.330000 sys 0.010000 (best of 28)
! wall 0.335932 comb 0.330000 user 0.290000 sys 0.040000 (best of 30)
! read w/ reused fd
! wall 0.342326 comb 0.340000 user 0.320000 sys 0.020000 (best of 29)
! wall 0.332857 comb 0.340000 user 0.290000 sys 0.050000 (best of 30)
! read batch
! wall 0.023623 comb 0.020000 user 0.000000 sys 0.020000 (best of 124)
! wall 0.023666 comb 0.020000 user 0.000000 sys 0.020000 (best of 125)
! read batch w/ reused fd
! wall 0.023828 comb 0.020000 user 0.000000 sys 0.020000 (best of 124)
! wall 0.023556 comb 0.020000 user 0.000000 sys 0.020000 (best of 126)
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 06 May 2017 12:02:31 -0700 |
parents | 2912b06905dc |
children | bd872f64a8ba |
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 tempfile |
2ed0b3f9f79e
statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30255
diff
changeset
|
116 import threading |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
117 import time |
30256
2ed0b3f9f79e
statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30255
diff
changeset
|
118 |
30578
c6ce11f2ee50
py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30568
diff
changeset
|
119 from . import ( |
30637
344e68882cd3
py3: replace os.environ with encoding.environ (part 4 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30578
diff
changeset
|
120 encoding, |
30578
c6ce11f2ee50
py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30568
diff
changeset
|
121 pycompat, |
c6ce11f2ee50
py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30568
diff
changeset
|
122 ) |
c6ce11f2ee50
py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30568
diff
changeset
|
123 |
30256
2ed0b3f9f79e
statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30255
diff
changeset
|
124 defaultdict = collections.defaultdict |
2ed0b3f9f79e
statprof: use absolute_imports
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30255
diff
changeset
|
125 contextmanager = contextlib.contextmanager |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
126 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
127 __all__ = ['start', 'stop', 'reset', 'display', 'profile'] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
128 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
129 skips = set(["util.py:check", "extensions.py:closure", |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
130 "color.py:colorcmd", "dispatch.py:checkargs", |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
131 "dispatch.py:<lambda>", "dispatch.py:_runcatch", |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
132 "dispatch.py:_dispatch", "dispatch.py:_runcommand", |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
133 "pager.py:pagecmd", "dispatch.py:run", |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
134 "dispatch.py:dispatch", "dispatch.py:runcommand", |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
135 "hg.py:<module>", "evolve.py:warnobserrors", |
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 ########################################################################### |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
139 ## Utils |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
140 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
141 def clock(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
142 times = os.times() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
143 return times[0] + times[1] |
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 ########################################################################### |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
147 ## Collection data structures |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
148 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
149 class ProfileState(object): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
150 def __init__(self, frequency=None): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
151 self.reset(frequency) |
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 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
155 self.accumulated_time = 0.0 |
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): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
174 self.accumulated_time += stop_time - self.last_start_time |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
175 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
176 def seconds_per_sample(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
177 return self.accumulated_time / len(self.samples) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
178 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
179 state = ProfileState() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
180 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
181 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
182 class CodeSite(object): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
183 cache = {} |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
184 |
30568
bb35fe8621f5
py3: use unicodes in __slots__
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30299
diff
changeset
|
185 __slots__ = (u'path', u'lineno', u'function', u'source') |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
186 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
187 def __init__(self, path, lineno, function): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
188 self.path = path |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
189 self.lineno = lineno |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
190 self.function = function |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
191 self.source = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
192 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
193 def __eq__(self, other): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
194 try: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
195 return (self.lineno == other.lineno and |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
196 self.path == other.path) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
197 except: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
198 return False |
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 __hash__(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
201 return hash((self.lineno, self.path)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
202 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
203 @classmethod |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
204 def get(cls, path, lineno, function): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
205 k = (path, lineno) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
206 try: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
207 return cls.cache[k] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
208 except KeyError: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
209 v = cls(path, lineno, function) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
210 cls.cache[k] = v |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
211 return v |
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 getsource(self, length): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
214 if self.source is None: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
215 lineno = self.lineno - 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
216 fp = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
217 try: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
218 fp = open(self.path) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
219 for i, line in enumerate(fp): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
220 if i == lineno: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
221 self.source = line.strip() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
222 break |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
223 except: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
224 pass |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
225 finally: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
226 if fp: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
227 fp.close() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
228 if self.source is None: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
229 self.source = '' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
230 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
231 source = self.source |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
232 if len(source) > length: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
233 source = source[:(length - 3)] + "..." |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
234 return source |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
235 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
236 def filename(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
237 return os.path.basename(self.path) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
238 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
239 class Sample(object): |
30568
bb35fe8621f5
py3: use unicodes in __slots__
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30299
diff
changeset
|
240 __slots__ = (u'stack', u'time') |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
241 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
242 def __init__(self, stack, time): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
243 self.stack = stack |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
244 self.time = time |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
245 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
246 @classmethod |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
247 def from_frame(cls, frame, time): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
248 stack = [] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
249 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
250 while frame: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
251 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
|
252 frame.f_code.co_name)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
253 frame = frame.f_back |
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 return Sample(stack, time) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
256 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
257 ########################################################################### |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
258 ## SIGPROF handler |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
259 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
260 def profile_signal_handler(signum, frame): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
261 if state.profile_level > 0: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
262 now = clock() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
263 state.accumulate_time(now) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
264 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
265 state.samples.append(Sample.from_frame(frame, state.accumulated_time)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
266 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
267 signal.setitimer(signal.ITIMER_PROF, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
268 state.sample_interval, 0.0) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
269 state.last_start_time = now |
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 stopthread = threading.Event() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
272 def samplerthread(tid): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
273 while not stopthread.is_set(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
274 now = clock() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
275 state.accumulate_time(now) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
276 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
277 frame = sys._current_frames()[tid] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
278 state.samples.append(Sample.from_frame(frame, state.accumulated_time)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
279 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
280 state.last_start_time = now |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
281 time.sleep(state.sample_interval) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
282 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
283 stopthread.clear() |
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 ########################################################################### |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
286 ## Profiling API |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
287 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
288 def is_active(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
289 return state.profile_level > 0 |
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 lastmechanism = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
292 def start(mechanism='thread'): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
293 '''Install the profiling signal handler, and start profiling.''' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
294 state.profile_level += 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
295 if state.profile_level == 1: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
296 state.last_start_time = clock() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
297 rpt = state.remaining_prof_time |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
298 state.remaining_prof_time = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
299 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
300 global lastmechanism |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
301 lastmechanism = mechanism |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
302 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
303 if mechanism == 'signal': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
304 signal.signal(signal.SIGPROF, profile_signal_handler) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
305 signal.setitimer(signal.ITIMER_PROF, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
306 rpt or state.sample_interval, 0.0) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
307 elif mechanism == 'thread': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
308 frame = inspect.currentframe() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
309 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
|
310 state.thread = threading.Thread(target=samplerthread, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
311 args=(tid,), name="samplerthread") |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
312 state.thread.start() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
313 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
314 def stop(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
315 '''Stop profiling, and uninstall the profiling signal handler.''' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
316 state.profile_level -= 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
317 if state.profile_level == 0: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
318 if lastmechanism == 'signal': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
319 rpt = signal.setitimer(signal.ITIMER_PROF, 0.0, 0.0) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
320 signal.signal(signal.SIGPROF, signal.SIG_IGN) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
321 state.remaining_prof_time = rpt[0] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
322 elif lastmechanism == 'thread': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
323 stopthread.set() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
324 state.thread.join() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
325 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
326 state.accumulate_time(clock()) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
327 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
|
328 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
|
329 if statprofpath: |
f42cd5434cc2
statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30254
diff
changeset
|
330 save_data(statprofpath) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
331 |
30299
1e5346313963
statprof: return state from stop()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30258
diff
changeset
|
332 return state |
1e5346313963
statprof: return state from stop()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30258
diff
changeset
|
333 |
30255
f42cd5434cc2
statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30254
diff
changeset
|
334 def save_data(path): |
f42cd5434cc2
statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30254
diff
changeset
|
335 with open(path, 'w+') as file: |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
336 file.write(str(state.accumulated_time) + '\n') |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
337 for sample in state.samples: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
338 time = str(sample.time) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
339 stack = sample.stack |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
340 sites = ['\1'.join([s.path, str(s.lineno), s.function]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
341 for s in stack] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
342 file.write(time + '\0' + '\0'.join(sites) + '\n') |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
343 |
30255
f42cd5434cc2
statprof: require paths to save or load profile data
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30254
diff
changeset
|
344 def load_data(path): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
345 lines = open(path, 'r').read().splitlines() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
346 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
347 state.accumulated_time = float(lines[0]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
348 state.samples = [] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
349 for line in lines[1:]: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
350 parts = line.split('\0') |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
351 time = float(parts[0]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
352 rawsites = parts[1:] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
353 sites = [] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
354 for rawsite in rawsites: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
355 siteparts = rawsite.split('\1') |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
356 sites.append(CodeSite.get(siteparts[0], int(siteparts[1]), |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
357 siteparts[2])) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
358 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
359 state.samples.append(Sample(sites, time)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
360 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
361 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
362 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
363 def reset(frequency=None): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
364 '''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
|
365 profiler is running. |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
366 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
367 The optional frequency argument specifies the number of samples to |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
368 collect per second.''' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
369 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
|
370 CodeSite.cache.clear() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
371 state.reset(frequency) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
372 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
373 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
374 @contextmanager |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
375 def profile(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
376 start() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
377 try: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
378 yield |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
379 finally: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
380 stop() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
381 display() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
382 |
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 ########################################################################### |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
385 ## Reporting API |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
386 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
387 class SiteStats(object): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
388 def __init__(self, site): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
389 self.site = site |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
390 self.selfcount = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
391 self.totalcount = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
392 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
393 def addself(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
394 self.selfcount += 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
395 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
396 def addtotal(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
397 self.totalcount += 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
398 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
399 def selfpercent(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
400 return self.selfcount / len(state.samples) * 100 |
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 def totalpercent(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
403 return self.totalcount / len(state.samples) * 100 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
404 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
405 def selfseconds(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
406 return self.selfcount * state.seconds_per_sample() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
407 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
408 def totalseconds(self): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
409 return self.totalcount * state.seconds_per_sample() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
410 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
411 @classmethod |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
412 def buildstats(cls, samples): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
413 stats = {} |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
414 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
415 for sample in samples: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
416 for i, site in enumerate(sample.stack): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
417 sitestat = stats.get(site) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
418 if not sitestat: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
419 sitestat = SiteStats(site) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
420 stats[site] = sitestat |
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 sitestat.addtotal() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
423 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
424 if i == 0: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
425 sitestat.addself() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
426 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
427 return [s for s in stats.itervalues()] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
428 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
429 class DisplayFormats: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
430 ByLine = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
431 ByMethod = 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
432 AboutMethod = 2 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
433 Hotpath = 3 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
434 FlameGraph = 4 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
435 Json = 5 |
30929
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
436 Chrome = 6 |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
437 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
438 def display(fp=None, format=3, data=None, **kwargs): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
439 '''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
|
440 data = data or state |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
441 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
442 if fp is None: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
443 import sys |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
444 fp = sys.stdout |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
445 if len(data.samples) == 0: |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
446 print('No samples recorded.', file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
447 return |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
448 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
449 if format == DisplayFormats.ByLine: |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
450 display_by_line(data, fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
451 elif format == DisplayFormats.ByMethod: |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
452 display_by_method(data, fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
453 elif format == DisplayFormats.AboutMethod: |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
454 display_about_method(data, fp, **kwargs) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
455 elif format == DisplayFormats.Hotpath: |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
456 display_hotpath(data, fp, **kwargs) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
457 elif format == DisplayFormats.FlameGraph: |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
458 write_to_flame(data, fp, **kwargs) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
459 elif format == DisplayFormats.Json: |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
460 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
|
461 elif format == DisplayFormats.Chrome: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
462 write_to_chrome(data, fp, **kwargs) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
463 else: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
464 raise Exception("Invalid display format") |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
465 |
30929
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
466 if format not in (DisplayFormats.Json, DisplayFormats.Chrome): |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
467 print('---', file=fp) |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
468 print('Sample count: %d' % len(data.samples), file=fp) |
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
469 print('Total time: %f seconds' % data.accumulated_time, file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
470 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
471 def display_by_line(data, fp): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
472 '''Print the profiler data with each sample line represented |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
473 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
|
474 stats = SiteStats.buildstats(data.samples) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
475 stats.sort(reverse=True, key=lambda x: x.selfseconds()) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
476 |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
477 print('%5.5s %10.10s %7.7s %-8.8s' % |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
478 ('% ', 'cumulative', 'self', ''), file=fp) |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
479 print('%5.5s %9.9s %8.8s %-8.8s' % |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
480 ("time", "seconds", "seconds", "name"), file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
481 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
482 for stat in stats: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
483 site = stat.site |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
484 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
|
485 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
|
486 stat.totalseconds(), |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
487 stat.selfseconds(), |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
488 sitelabel), |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
489 file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
490 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
491 def display_by_method(data, fp): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
492 '''Print the profiler data with each sample function represented |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
493 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
|
494 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
|
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 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
500 stats = SiteStats.buildstats(data.samples) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
501 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
502 grouped = defaultdict(list) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
503 for stat in stats: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
504 grouped[stat.site.filename() + ":" + stat.site.function].append(stat) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
505 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
506 # compute sums for each function |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
507 functiondata = [] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
508 for fname, sitestats in grouped.iteritems(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
509 total_cum_sec = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
510 total_self_sec = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
511 total_percent = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
512 for stat in sitestats: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
513 total_cum_sec += stat.totalseconds() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
514 total_self_sec += stat.selfseconds() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
515 total_percent += stat.selfpercent() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
516 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
517 functiondata.append((fname, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
518 total_cum_sec, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
519 total_self_sec, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
520 total_percent, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
521 sitestats)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
522 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
523 # sort by total self sec |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
524 functiondata.sort(reverse=True, key=lambda x: x[2]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
525 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
526 for function in functiondata: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
527 if function[3] < 0.05: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
528 continue |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
529 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
|
530 function[1], # total cum sec |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
531 function[2], # total self sec |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
532 function[0]), # file:function |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
533 file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
534 function[4].sort(reverse=True, key=lambda i: i.selfseconds()) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
535 for stat in function[4]: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
536 # only show line numbers for significant locations (>1% time spent) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
537 if stat.selfpercent() > 1: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
538 source = stat.site.getsource(25) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
539 stattuple = (stat.selfpercent(), stat.selfseconds(), |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
540 stat.site.lineno, source) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
541 |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
542 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
|
543 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
544 def display_about_method(data, fp, function=None, **kwargs): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
545 if function is None: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
546 raise Exception("Invalid function") |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
547 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
548 filename = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
549 if ':' in function: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
550 filename, function = function.split(':') |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
551 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
552 relevant_samples = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
553 parents = {} |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
554 children = {} |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
555 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
556 for sample in data.samples: |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
557 for i, site in enumerate(sample.stack): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
558 if site.function == function and (not filename |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
559 or site.filename() == filename): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
560 relevant_samples += 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
561 if i != len(sample.stack) - 1: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
562 parent = sample.stack[i + 1] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
563 if parent in parents: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
564 parents[parent] = parents[parent] + 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
565 else: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
566 parents[parent] = 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
567 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
568 if site in children: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
569 children[site] = children[site] + 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
570 else: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
571 children[site] = 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
572 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
573 parents = [(parent, count) for parent, count in parents.iteritems()] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
574 parents.sort(reverse=True, key=lambda x: x[1]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
575 for parent, count in parents: |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
576 print('%6.2f%% %s:%s line %s: %s' % |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
577 (count / relevant_samples * 100, parent.filename(), |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
578 parent.function, parent.lineno, parent.getsource(50)), file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
579 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
580 stats = SiteStats.buildstats(data.samples) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
581 stats = [s for s in stats |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
582 if s.site.function == function and |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
583 (not filename or s.site.filename() == filename)] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
584 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
585 total_cum_sec = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
586 total_self_sec = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
587 total_self_percent = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
588 total_cum_percent = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
589 for stat in stats: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
590 total_cum_sec += stat.totalseconds() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
591 total_self_sec += stat.selfseconds() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
592 total_self_percent += stat.selfpercent() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
593 total_cum_percent += stat.totalpercent() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
594 |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
595 print( |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
596 '\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
|
597 ( |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
598 filename or '___', |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
599 function, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
600 total_cum_sec, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
601 total_cum_percent, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
602 total_self_sec, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
603 total_self_percent |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
604 ), file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
605 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
606 children = [(child, count) for child, count in children.iteritems()] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
607 children.sort(reverse=True, key=lambda x: x[1]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
608 for child, count in children: |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
609 print(' %6.2f%% line %s: %s' % |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
610 (count / relevant_samples * 100, child.lineno, |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
611 child.getsource(50)), file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
612 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
613 def display_hotpath(data, fp, limit=0.05, **kwargs): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
614 class HotNode(object): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
615 def __init__(self, site): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
616 self.site = site |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
617 self.count = 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
618 self.children = {} |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
619 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
620 def add(self, stack, time): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
621 self.count += time |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
622 site = stack[0] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
623 child = self.children.get(site) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
624 if not child: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
625 child = HotNode(site) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
626 self.children[site] = child |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
627 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
628 if len(stack) > 1: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
629 i = 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
630 # Skip boiler plate parts of the stack |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
631 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
|
632 i += 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
633 if i < len(stack): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
634 child.add(stack[i:], time) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
635 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
636 root = HotNode(None) |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
637 lasttime = data.samples[0].time |
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
638 for sample in data.samples: |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
639 root.add(sample.stack[::-1], sample.time - lasttime) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
640 lasttime = sample.time |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
641 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
642 def _write(node, depth, multiple_siblings): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
643 site = node.site |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
644 visiblechildren = [c for c in node.children.itervalues() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
645 if c.count >= (limit * root.count)] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
646 if site: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
647 indent = depth * 2 - 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
648 filename = '' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
649 function = '' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
650 if len(node.children) > 0: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
651 childsite = list(node.children.itervalues())[0].site |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
652 filename = (childsite.filename() + ':').ljust(15) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
653 function = childsite.function |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
654 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
655 # lots of string formatting |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
656 listpattern = ''.ljust(indent) +\ |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
657 ('\\' if multiple_siblings else '|') +\ |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
658 ' %4.1f%% %s %s' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
659 liststring = listpattern % (node.count / root.count * 100, |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
660 filename, function) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
661 codepattern = '%' + str(55 - len(liststring)) + 's %s: %s' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
662 codestring = codepattern % ('line', site.lineno, site.getsource(30)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
663 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
664 finalstring = liststring + codestring |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
665 childrensamples = sum([c.count for c in node.children.itervalues()]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
666 # 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
|
667 if node.count - childrensamples > (0.1 * root.count): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
668 finalstring = '\033[91m' + finalstring + '\033[0m' |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
669 # Make frames that didn't actually perform work dark grey |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
670 elif node.count - childrensamples == 0: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
671 finalstring = '\033[90m' + finalstring + '\033[0m' |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
672 print(finalstring, file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
673 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
674 newdepth = depth |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
675 if len(visiblechildren) > 1 or multiple_siblings: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
676 newdepth += 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
677 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
678 visiblechildren.sort(reverse=True, key=lambda x: x.count) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
679 for child in visiblechildren: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
680 _write(child, newdepth, len(visiblechildren) > 1) |
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 if root.count > 0: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
683 _write(root, 0, False) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
684 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
685 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
|
686 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
|
687 scriptpath = encoding.environ['HOME'] + '/flamegraph.pl' |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
688 if not os.path.exists(scriptpath): |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
689 print("error: missing %s" % scriptpath, file=fp) |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
690 print("get it here: https://github.com/brendangregg/FlameGraph", |
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
691 file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
692 return |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
693 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
694 fd, path = tempfile.mkstemp() |
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 file = open(path, "w+") |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
697 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
698 lines = {} |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
699 for sample in data.samples: |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
700 sites = [s.function for s in sample.stack] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
701 sites.reverse() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
702 line = ';'.join(sites) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
703 if line in lines: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
704 lines[line] = lines[line] + 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
705 else: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
706 lines[line] = 1 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
707 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
708 for line, count in lines.iteritems(): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
709 file.write("%s %s\n" % (line, count)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
710 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
711 file.close() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
712 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
713 if outputfile is None: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
714 outputfile = '~/flamegraph.svg' |
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 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
|
717 print("Written to %s" % outputfile, file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
718 |
30928
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
719 _pathcache = {} |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
720 def simplifypath(path): |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
721 '''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
|
722 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
|
723 on.''' |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
724 |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
725 if path in _pathcache: |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
726 return _pathcache[path] |
31074
2912b06905dc
py3: use pycompat.fsencode() to convert __file__ to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30929
diff
changeset
|
727 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
|
728 for p in [hgpath] + sys.path: |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
729 prefix = p + os.sep |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
730 if path.startswith(prefix): |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
731 path = path[len(prefix):] |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
732 break |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
733 _pathcache[path] = path |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
734 return path |
be3a4fde38eb
statprof: add a path simplification function
Bryan O'Sullivan <bryano@fb.com>
parents:
30845
diff
changeset
|
735 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
736 def write_to_json(data, fp): |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
737 samples = [] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
738 |
30258
eea89068a98d
statprof: pass data structure to display functions
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30257
diff
changeset
|
739 for sample in data.samples: |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
740 stack = [] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
741 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
742 for frame in sample.stack: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
743 stack.append((frame.path, frame.lineno, frame.function)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
744 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
745 samples.append((sample.time, stack)) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
746 |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
747 print(json.dumps(samples), file=fp) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
748 |
30929
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
749 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
|
750 samples = [] |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
751 laststack = collections.deque() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
752 lastseen = collections.deque() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
753 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
754 # 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
|
755 # 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
|
756 # 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
|
757 stack2id = {} |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
758 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
|
759 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
760 def stackid(stack): |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
761 if not stack: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
762 return |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
763 if stack in stack2id: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
764 return stack2id[stack] |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
765 parent = stackid(stack[1:]) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
766 myid = len(stack2id) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
767 stack2id[stack] = myid |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
768 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
|
769 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
|
770 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
|
771 return myid |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
772 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
773 def endswith(a, b): |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
774 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
|
775 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
776 # 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
|
777 # 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
|
778 # 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
|
779 # 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
|
780 # millisecond in length. |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
781 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
782 clamp = 0.001 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
783 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
784 # 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
|
785 # 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
|
786 # |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
787 # * 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
|
788 # 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
|
789 # |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
790 # * 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
|
791 # 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
|
792 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
793 blacklist = set() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
794 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
|
795 minthreshold = totaltime * minthreshold |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
796 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
|
797 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
798 def poplast(): |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
799 oldsid = stackid(tuple(laststack)) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
800 oldcat, oldfunc = laststack.popleft() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
801 oldtime, oldidx = lastseen.popleft() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
802 duration = sample.time - oldtime |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
803 if minthreshold <= duration <= maxthreshold: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
804 # 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
|
805 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
|
806 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
|
807 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
|
808 else: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
809 blacklist.add(oldidx) |
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 # 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
|
812 # 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
|
813 |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
814 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
|
815 tos = sample.stack[0] |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
816 name = tos.function |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
817 path = simplifypath(tos.path) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
818 category = '%s:%d' % (path, tos.lineno) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
819 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
|
820 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
|
821 qstack = collections.deque(stack) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
822 if laststack == qstack: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
823 continue |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
824 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
|
825 laststack.pop() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
826 qstack.pop() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
827 while laststack: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
828 poplast() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
829 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
|
830 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
|
831 laststack.appendleft(f) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
832 path, name = f |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
833 sid = stackid(tuple(laststack)) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
834 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
|
835 sf=sid, pid=0)) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
836 laststack = collections.deque(stack) |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
837 while laststack: |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
838 poplast() |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
839 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
|
840 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
|
841 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
|
842 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
|
843 fp.write('\n') |
cb440e7af05d
statprof: allow rendering in the Chrome trace viewer format
Bryan O'Sullivan <bryano@fb.com>
parents:
30928
diff
changeset
|
844 |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
845 def printusage(): |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
846 print(""" |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
847 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
|
848 the following forms: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
849 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
850 usage: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
851 hotpath [-l --limit percent] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
852 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
|
853 Red calls take over 10%% of the total time themselves. |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
854 lines |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
855 Shows the actual sampled lines. |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
856 functions |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
857 Shows the samples grouped by function. |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
858 function [filename:]functionname |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
859 Shows the callers and callees of a particular function. |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
860 flame [-s --script-path] [-o --output-file path] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
861 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
|
862 Requires that ~/flamegraph.pl exist. |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
863 (Specify alternate script path with --script-path.)""") |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
864 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
865 def main(argv=None): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
866 if argv is None: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
867 argv = sys.argv |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
868 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
869 if len(argv) == 1: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
870 printusage() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
871 return 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
872 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
873 displayargs = {} |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
874 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
875 optstart = 2 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
876 displayargs['function'] = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
877 if argv[1] == 'hotpath': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
878 displayargs['format'] = DisplayFormats.Hotpath |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
879 elif argv[1] == 'lines': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
880 displayargs['format'] = DisplayFormats.ByLine |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
881 elif argv[1] == 'functions': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
882 displayargs['format'] = DisplayFormats.ByMethod |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
883 elif argv[1] == 'function': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
884 displayargs['format'] = DisplayFormats.AboutMethod |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
885 displayargs['function'] = argv[2] |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
886 optstart = 3 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
887 elif argv[1] == 'flame': |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
888 displayargs['format'] = DisplayFormats.FlameGraph |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
889 else: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
890 printusage() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
891 return 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
892 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
893 # process options |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
894 try: |
30578
c6ce11f2ee50
py3: make a bytes version of getopt.getopt()
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30568
diff
changeset
|
895 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
|
896 ["help", "limit=", "file=", "output-file=", "script-path="]) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
897 except getopt.error as msg: |
30257
7428223ed7c2
statprof: use print function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30256
diff
changeset
|
898 print(msg) |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
899 printusage() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
900 return 2 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
901 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
902 displayargs['limit'] = 0.05 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
903 path = None |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
904 for o, value in opts: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
905 if o in ("-l", "--limit"): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
906 displayargs['limit'] = float(value) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
907 elif o in ("-f", "--file"): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
908 path = value |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
909 elif o in ("-o", "--output-file"): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
910 displayargs['outputfile'] = value |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
911 elif o in ("-p", "--script-path"): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
912 displayargs['scriptpath'] = value |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
913 elif o in ("-h", "help"): |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
914 printusage() |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
915 return 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
916 else: |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
917 assert False, "unhandled option %s" % o |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
918 |
30845
262c2be8ea5a
statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30637
diff
changeset
|
919 if not path: |
262c2be8ea5a
statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30637
diff
changeset
|
920 print('must specify --file to load') |
262c2be8ea5a
statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30637
diff
changeset
|
921 return 1 |
262c2be8ea5a
statprof: require input file
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30637
diff
changeset
|
922 |
30253
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
923 load_data(path=path) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
924 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
925 display(**displayargs) |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
926 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
927 return 0 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
928 |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
929 if __name__ == "__main__": |
b032a7b676c6
statprof: vendor statprof.py
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
930 sys.exit(main()) |