##// END OF EJS Templates
profiling: add a py-spy profiling backend...
Arseniy Alekseyev -
r52654:812a094a default
parent child Browse files
Show More
@@ -1811,6 +1811,20 b' name = "type"'
1811 default = "stat"
1811 default = "stat"
1812
1812
1813 [[items]]
1813 [[items]]
1814 section = "profiling"
1815 name = "py-spy.exe"
1816 default = "py-spy"
1817
1818 [[items]]
1819 section = "profiling"
1820 name = "py-spy.freq"
1821 default = 100
1822
1823 [[items]]
1824 section = "profiling"
1825 name = "py-spy.format"
1826
1827 [[items]]
1814 section = "progress"
1828 section = "progress"
1815 name = "assume-tty"
1829 name = "assume-tty"
1816 default = false
1830 default = false
@@ -7,6 +7,9 b''
7
7
8
8
9 import contextlib
9 import contextlib
10 import os
11 import signal
12 import subprocess
10
13
11 from .i18n import _
14 from .i18n import _
12 from .pycompat import (
15 from .pycompat import (
@@ -175,6 +178,50 b' def statprofile(ui, fp):'
175 fp.flush()
178 fp.flush()
176
179
177
180
181 @contextlib.contextmanager
182 def pyspy_profile(ui, fp):
183 exe = ui.config(b'profiling', b'py-spy.exe')
184
185 freq = ui.configint(b'profiling', b'py-spy.freq')
186
187 format = ui.config(b'profiling', b'py-spy.format')
188
189 fd = fp.fileno()
190
191 output_path = "/dev/fd/%d" % (fd)
192
193 my_pid = os.getpid()
194
195 cmd = [
196 exe,
197 "record",
198 "--pid",
199 str(my_pid),
200 "--native",
201 "--rate",
202 str(freq),
203 "--output",
204 output_path,
205 ]
206
207 if format:
208 cmd.extend(["--format", format])
209
210 proc = subprocess.Popen(
211 cmd,
212 pass_fds={fd},
213 stdout=subprocess.PIPE,
214 )
215
216 _ = proc.stdout.readline()
217
218 try:
219 yield
220 finally:
221 os.kill(proc.pid, signal.SIGINT)
222 proc.communicate()
223
224
178 class profile:
225 class profile:
179 """Start profiling.
226 """Start profiling.
180
227
@@ -214,7 +261,7 b' class profile:'
214 proffn = None
261 proffn = None
215 if profiler is None:
262 if profiler is None:
216 profiler = self._ui.config(b'profiling', b'type')
263 profiler = self._ui.config(b'profiling', b'type')
217 if profiler not in (b'ls', b'stat', b'flame'):
264 if profiler not in (b'ls', b'stat', b'flame', b'py-spy'):
218 # try load profiler from extension with the same name
265 # try load profiler from extension with the same name
219 proffn = _loadprofiler(self._ui, profiler)
266 proffn = _loadprofiler(self._ui, profiler)
220 if proffn is None:
267 if proffn is None:
@@ -257,6 +304,8 b' class profile:'
257 proffn = lsprofile
304 proffn = lsprofile
258 elif profiler == b'flame':
305 elif profiler == b'flame':
259 proffn = flameprofile
306 proffn = flameprofile
307 elif profiler == b'py-spy':
308 proffn = pyspy_profile
260 else:
309 else:
261 proffn = statprofile
310 proffn = statprofile
262
311
General Comments 0
You need to be logged in to leave comments. Login now