annotate mercurial/profiling.py @ 51813:812a094a7477

profiling: add a py-spy profiling backend The recommended way to use this backend is by setting the config `profiling.output` to point to a file because py-spy output is not human-readable.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 01 Aug 2024 13:07:13 +0100
parents 1574718fa62f
children 3785814bc2b7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 # profiling.py - profiling functions
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 #
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # Copyright 2016 Gregory Szorc <gregory.szorc@gmail.com>
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 #
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
9 import contextlib
51813
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
10 import os
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
11 import signal
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
12 import subprocess
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 from .i18n import _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
15 from .pycompat import (
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
16 open,
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43085
diff changeset
17 )
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18 from . import (
30820
6a70cf94d1b5 py3: replace pycompat.getenv with encoding.environ.get
Pulkit Goyal <7895pulkit@gmail.com>
parents: 30667
diff changeset
19 encoding,
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
20 error,
32455
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
21 extensions,
36712
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
22 pycompat,
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
23 util,
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
24 )
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
26
32455
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
27 def _loadprofiler(ui, profiler):
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
28 """load profiler extension. return profile method, or None on failure"""
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
29 extname = profiler
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
30 extensions.loadall(ui, whitelist=[extname])
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
31 try:
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
32 mod = extensions.find(extname)
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
33 except KeyError:
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
34 return None
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
35 else:
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
36 return getattr(mod, 'profile', None)
f40dc6f7c12f profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents: 30995
diff changeset
37
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
38
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
39 @contextlib.contextmanager
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
40 def lsprofile(ui, fp):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
41 format = ui.config(b'profiling', b'format')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
42 field = ui.config(b'profiling', b'sort')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
43 limit = ui.configint(b'profiling', b'limit')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
44 climit = ui.configint(b'profiling', b'nested')
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
45
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
46 if format not in [b'text', b'kcachegrind']:
43117
8ff1ecfadcd1 cleanup: join string literals that are already on one line
Martin von Zweigbergk <martinvonz@google.com>
parents: 43089
diff changeset
47 ui.warn(_(b"unrecognized profiling format '%s' - Ignored\n") % format)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
48 format = b'text'
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
49
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
50 try:
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
51 from . import lsprof
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
52 except ImportError:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
53 raise error.Abort(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
54 _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
55 b'lsprof not available - install from '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
56 b'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
57 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
58 )
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
59 p = lsprof.Profiler()
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
60 p.enable(subcalls=True)
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
61 try:
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
62 yield
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
63 finally:
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64 p.disable()
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
66 if format == b'kcachegrind':
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 from . import lsprofcalltree
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
68
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69 calltree = lsprofcalltree.KCacheGrind(p)
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 calltree.output(fp)
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 else:
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
72 # format == 'text'
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
73 stats = lsprof.Stats(p.getstats())
40192
b8f6a99ad89b py3: convert sorting field to sysstr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38272
diff changeset
74 stats.sort(pycompat.sysstr(field))
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75 stats.pprint(limit=limit, file=fp, climit=climit)
51613
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
76 fp.flush()
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
77
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
78
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
79 @contextlib.contextmanager
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
80 def flameprofile(ui, fp):
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
81 try:
43764
6c8ba31405d9 profiling: disable the import-error warning for the flamegraph module
Matt Harbison <matt_harbison@yahoo.com>
parents: 43554
diff changeset
82 from flamegraph import flamegraph # pytype: disable=import-error
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
83 except ImportError:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
84 raise error.Abort(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
85 _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
86 b'flamegraph not available - install from '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
87 b'https://github.com/evanhempel/python-flamegraph'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
88 )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
89 )
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
90 # developer config: profiling.freq
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
91 freq = ui.configint(b'profiling', b'freq')
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
92 filter_ = None
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
93 collapse_recursion = True
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
94 thread = flamegraph.ProfileThread(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
95 fp, 1.0 / freq, filter_, collapse_recursion
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
96 )
30995
22fbca1d11ed mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents: 30950
diff changeset
97 start_time = util.timer()
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
98 try:
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
99 thread.start()
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
100 yield
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
101 finally:
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
102 thread.stop()
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
103 thread.join()
51613
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
104 m = b'Collected %d stack frames (%d unique) in %2.2f seconds.'
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
105 m %= (
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
106 (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
107 util.timer() - start_time,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
108 thread.num_frames(),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
109 thread.num_frames(unique=True),
51613
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
110 ),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
111 )
51613
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
112 print(m, flush=True)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
113
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
114
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
115 @contextlib.contextmanager
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
116 def statprofile(ui, fp):
30329
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
117 from . import statprof
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
118
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
119 freq = ui.configint(b'profiling', b'freq')
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
120 if freq > 0:
29796
88d3c1ab03a7 profiling: don't error with statprof when profiling has already started
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29795
diff changeset
121 # Cannot reset when profiler is already active. So silently no-op.
88d3c1ab03a7 profiling: don't error with statprof when profiling has already started
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29795
diff changeset
122 if statprof.state.profile_level == 0:
88d3c1ab03a7 profiling: don't error with statprof when profiling has already started
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29795
diff changeset
123 statprof.reset(freq)
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
124 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
125 ui.warn(_(b"invalid sampling frequency '%s' - ignoring\n") % freq)
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
126
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
127 track = ui.config(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
128 b'profiling', b'time-track', pycompat.iswindows and b'cpu' or b'real'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
129 )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
130 statprof.start(mechanism=b'thread', track=track)
30329
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
131
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
132 try:
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
133 yield
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
134 finally:
30329
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
135 data = statprof.stop()
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
136
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
137 profformat = ui.config(b'profiling', b'statformat')
30329
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
138
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
139 formats = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
140 b'byline': statprof.DisplayFormats.ByLine,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
141 b'bymethod': statprof.DisplayFormats.ByMethod,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
142 b'hotpath': statprof.DisplayFormats.Hotpath,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
143 b'json': statprof.DisplayFormats.Json,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
144 b'chrome': statprof.DisplayFormats.Chrome,
30329
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
145 }
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
146
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
147 if profformat in formats:
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
148 displayformat = formats[profformat]
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
149 else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
150 ui.warn(_(b'unknown profiler output format: %s\n') % profformat)
30329
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
151 displayformat = statprof.DisplayFormats.Hotpath
faf1b8923da2 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29796
diff changeset
152
30950
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
153 kwargs = {}
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
154
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
155 def fraction(s):
32996
41b081ac2145 profiling: cope with configwith default value handling changes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32869
diff changeset
156 if isinstance(s, (float, int)):
41b081ac2145 profiling: cope with configwith default value handling changes
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32869
diff changeset
157 return float(s)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
158 if s.endswith(b'%'):
30950
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
159 v = float(s[:-1]) / 100
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
160 else:
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
161 v = float(s)
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
162 if 0 <= v <= 1:
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
163 return v
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
164 raise ValueError(s)
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
165
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
166 if profformat == b'chrome':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
167 showmin = ui.configwith(fraction, b'profiling', b'showmin', 0.005)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
168 showmax = ui.configwith(fraction, b'profiling', b'showmax')
30950
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
169 kwargs.update(minthreshold=showmin, maxthreshold=showmax)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
170 elif profformat == b'hotpath':
33197
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32996
diff changeset
171 # inconsistent config: profiling.showmin
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
172 limit = ui.configwith(fraction, b'profiling', b'showmin', 0.05)
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43117
diff changeset
173 kwargs['limit'] = limit
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
174 showtime = ui.configbool(b'profiling', b'showtime')
43554
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43117
diff changeset
175 kwargs['showtime'] = showtime
30950
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
176
517bc1cd7033 profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents: 30820
diff changeset
177 statprof.display(fp, data=data, format=displayformat, **kwargs)
51613
1574718fa62f profiler: flush after writing the profiler output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50952
diff changeset
178 fp.flush()
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
179
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
180
51813
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
181 @contextlib.contextmanager
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
182 def pyspy_profile(ui, fp):
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
183 exe = ui.config(b'profiling', b'py-spy.exe')
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
184
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
185 freq = ui.configint(b'profiling', b'py-spy.freq')
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
186
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
187 format = ui.config(b'profiling', b'py-spy.format')
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
188
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
189 fd = fp.fileno()
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
190
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
191 output_path = "/dev/fd/%d" % (fd)
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
192
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
193 my_pid = os.getpid()
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
194
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
195 cmd = [
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
196 exe,
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
197 "record",
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
198 "--pid",
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
199 str(my_pid),
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
200 "--native",
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
201 "--rate",
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
202 str(freq),
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
203 "--output",
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
204 output_path,
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
205 ]
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
206
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
207 if format:
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
208 cmd.extend(["--format", format])
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
209
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
210 proc = subprocess.Popen(
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
211 cmd,
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
212 pass_fds={fd},
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
213 stdout=subprocess.PIPE,
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
214 )
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
215
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
216 _ = proc.stdout.readline()
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
217
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
218 try:
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
219 yield
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
220 finally:
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
221 os.kill(proc.pid, signal.SIGINT)
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
222 proc.communicate()
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
223
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
224
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
225 class profile:
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
226 """Start profiling.
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
227
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
228 Profiling is active when the context manager is active. When the context
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
229 manager exits, profiling results will be written to the configured output.
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
230 """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
231
32805
37ec8f24d912 profile: introduce a knob to control if the context is actually profiling
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32804
diff changeset
232 def __init__(self, ui, enabled=True):
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
233 self._ui = ui
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
234 self._output = None
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
235 self._fp = None
32824
2b0fc56840d0 profile: use explicit logic to control file closing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32823
diff changeset
236 self._fpdoclose = True
44267
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
237 self._flushfp = None
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
238 self._profiler = None
32805
37ec8f24d912 profile: introduce a knob to control if the context is actually profiling
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32804
diff changeset
239 self._enabled = enabled
32804
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
240 self._entered = False
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
241 self._started = False
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
242
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
243 def __enter__(self):
32804
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
244 self._entered = True
32805
37ec8f24d912 profile: introduce a knob to control if the context is actually profiling
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32804
diff changeset
245 if self._enabled:
37ec8f24d912 profile: introduce a knob to control if the context is actually profiling
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32804
diff changeset
246 self.start()
32806
0ead06d54ffe profile: make the contextmanager object available to the callers
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32805
diff changeset
247 return self
32804
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
248
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
249 def start(self):
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
250 """Start profiling.
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
251
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
252 The profiling will stop at the context exit.
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
253
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
254 If the profiler was already started, this has no effect."""
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
255 if not self._entered:
43765
882e633ac92c profiling: add a missing argument to the ProgrammingError constructor
Matt Harbison <matt_harbison@yahoo.com>
parents: 43764
diff changeset
256 raise error.ProgrammingError(b'use a context manager to start')
32804
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
257 if self._started:
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
258 return
086c1ef0f666 profile: introduce a "start" method to the profile context
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32803
diff changeset
259 self._started = True
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
260 profiler = encoding.environ.get(b'HGPROF')
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
261 proffn = None
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
262 if profiler is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
263 profiler = self._ui.config(b'profiling', b'type')
51813
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
264 if profiler not in (b'ls', b'stat', b'flame', b'py-spy'):
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
265 # try load profiler from extension with the same name
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
266 proffn = _loadprofiler(self._ui, profiler)
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
267 if proffn is None:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
268 self._ui.warn(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
269 _(b"unrecognized profiler '%s' - ignored\n") % profiler
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
270 )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
271 profiler = b'stat'
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
272
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
273 self._output = self._ui.config(b'profiling', b'output')
29792
2654a0aac80d profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
274
32827
336700745a5c profile: close 'fp' on error within '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32826
diff changeset
275 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
276 if self._output == b'blackbox':
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
277 self._fp = util.stringio()
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
278 elif self._output:
46958
5a6a1cd21f09 profiling: use `util.expandpath` instead of `ui.expandpath` for output
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44267
diff changeset
279 path = util.expandpath(self._output)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
280 self._fp = open(path, b'wb')
36712
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
281 elif pycompat.iswindows:
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
282 # parse escape sequence by win32print()
49037
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48966
diff changeset
283 class uifp:
36712
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
284 def __init__(self, ui):
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
285 self._ui = ui
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
286
36712
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
287 def write(self, data):
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
288 self._ui.write_err(data)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
289
36712
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
290 def flush(self):
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
291 self._ui.flush()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
292
36712
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
293 self._fpdoclose = False
e39953fdd924 profile: colorize output on Windows
Matt Harbison <matt_harbison@yahoo.com>
parents: 36430
diff changeset
294 self._fp = uifp(self._ui)
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
295 else:
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
296 self._fpdoclose = False
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
297 self._fp = self._ui.ferr
44267
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
298 # Ensure we've flushed fout before writing to ferr.
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
299 self._flushfp = self._ui.fout
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
300
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
301 if proffn is not None:
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
302 pass
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
303 elif profiler == b'ls':
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
304 proffn = lsprofile
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
305 elif profiler == b'flame':
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
306 proffn = flameprofile
51813
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
307 elif profiler == b'py-spy':
812a094a7477 profiling: add a py-spy profiling backend
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 51613
diff changeset
308 proffn = pyspy_profile
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
309 else:
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
310 proffn = statprofile
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
311
32826
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
312 self._profiler = proffn(self._ui, self._fp)
54b356d65079 profile: indent part of '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32825
diff changeset
313 self._profiler.__enter__()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
314 except: # re-raises
32827
336700745a5c profile: close 'fp' on error within '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32826
diff changeset
315 self._closefp()
336700745a5c profile: close 'fp' on error within '__enter__'
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32826
diff changeset
316 raise
29794
5d44197c208b profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29792
diff changeset
317
32803
4483696dacee profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32455
diff changeset
318 def __exit__(self, exception_type, exception_value, traceback):
32829
6675d23da748 profile: properly propagate exception from the sub-context manager
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32828
diff changeset
319 propagate = None
32828
062eb859d3ee profile: close 'fp' in all cases
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32827
diff changeset
320 if self._profiler is not None:
44267
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
321 self._uiflush()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
322 propagate = self._profiler.__exit__(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
323 exception_type, exception_value, traceback
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42439
diff changeset
324 )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
325 if self._output == b'blackbox':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
326 val = b'Profile:\n%s' % self._fp.getvalue()
32828
062eb859d3ee profile: close 'fp' in all cases
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32827
diff changeset
327 # ui.log treats the input as a format string,
062eb859d3ee profile: close 'fp' in all cases
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32827
diff changeset
328 # so we need to escape any % signs.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
329 val = val.replace(b'%', b'%%')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
330 self._ui.log(b'profile', val)
32825
3a4c677cbd6e profile: remove now useless indent
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32824
diff changeset
331 self._closefp()
32829
6675d23da748 profile: properly propagate exception from the sub-context manager
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32828
diff changeset
332 return propagate
32823
c0b2c8f25ad9 profiling: move 'fp' closing logic into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32808
diff changeset
333
c0b2c8f25ad9 profiling: move 'fp' closing logic into its own function
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32808
diff changeset
334 def _closefp(self):
32824
2b0fc56840d0 profile: use explicit logic to control file closing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32823
diff changeset
335 if self._fpdoclose and self._fp is not None:
2b0fc56840d0 profile: use explicit logic to control file closing
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32823
diff changeset
336 self._fp.close()
44267
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
337
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
338 def _uiflush(self):
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
339 if self._flushfp:
d6d4170882cd profiling: flush stdout before writing profile to stderr
Kyle Lippincott <spectral@google.com>
parents: 43765
diff changeset
340 self._flushfp.flush()