Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/profiling.py @ 32803:4483696dacee
profile: upgrade the "profile" context manager to a full class
So far we have been able to use a simple decorator for this. However using the
current context manager makes the scope of the profiling in dispatch
constrainted and the time frame to decide to enable profiling quite limited
(using "maybeprofile")
This is the first step toward the ability to enable the profiling from within
the profiling scope. eg::
with maybeprofiling(ui) as profiler:
...
bar.foo():
...
if options['profile']:
profiler.start()
...
fooz()
...
My target usecase is adding support for "--profile" to alias definitions with
effect. These are to be used with "profiling.output=blackbox" to gather data
about operation that get slow from time to time (eg: pull being minutes instead
of seconds from time to time).
Of course, in such case, the scope of the profiling would be smaller since
profiler would be started after running extensions 'reposetup' (and other
potentially costly logic), but these are not relevant for my target usecase
(multiple second commits, multiple tens of seconds pull).
Currently adding '--profile' to a command through alias requires to re-spin a
Mercurial binary (using "!$HG" in alias), which as a significant performance
impact, especially in context where startup performance is being worked on...
An alternative approach would be to stop using the context manager in dispatch
and move back to a try/finally setup.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 08 Jun 2017 01:38:48 +0100 |
parents | f40dc6f7c12f |
children | 086c1ef0f666 |
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 from __future__ import absolute_import, print_function |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
9 |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
10 import contextlib |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
11 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
12 from .i18n import _ |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
13 from . import ( |
30820
6a70cf94d1b5
py3: replace pycompat.getenv with encoding.environ.get
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30667
diff
changeset
|
14 encoding, |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
15 error, |
32455
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
16 extensions, |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
17 util, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
18 ) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
19 |
32455
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
20 def _loadprofiler(ui, profiler): |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
21 """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
|
22 extname = profiler |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
23 extensions.loadall(ui, whitelist=[extname]) |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
24 try: |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
25 mod = extensions.find(extname) |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
26 except KeyError: |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
27 return None |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
28 else: |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
29 return getattr(mod, 'profile', None) |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
30 |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
31 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
32 def lsprofile(ui, fp): |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
33 format = ui.config('profiling', 'format', default='text') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
34 field = ui.config('profiling', 'sort', default='inlinetime') |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
35 limit = ui.configint('profiling', 'limit', default=30) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
36 climit = ui.configint('profiling', 'nested', default=0) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
37 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
38 if format not in ['text', 'kcachegrind']: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
39 ui.warn(_("unrecognized profiling format '%s'" |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
40 " - Ignored\n") % format) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
41 format = 'text' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
42 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
43 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
44 from . import lsprof |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
45 except ImportError: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
46 raise error.Abort(_( |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
47 'lsprof not available - install from ' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
48 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/')) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
49 p = lsprof.Profiler() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
50 p.enable(subcalls=True) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
51 try: |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
52 yield |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
53 finally: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
54 p.disable() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
55 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
56 if format == 'kcachegrind': |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
57 from . import lsprofcalltree |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
58 calltree = lsprofcalltree.KCacheGrind(p) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
59 calltree.output(fp) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
60 else: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
61 # format == 'text' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
62 stats = lsprof.Stats(p.getstats()) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
63 stats.sort(field) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
64 stats.pprint(limit=limit, file=fp, climit=climit) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
65 |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
66 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
67 def flameprofile(ui, fp): |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
68 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
69 from flamegraph import flamegraph |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
70 except ImportError: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
71 raise error.Abort(_( |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
72 'flamegraph not available - install from ' |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
73 'https://github.com/evanhempel/python-flamegraph')) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
74 # developer config: profiling.freq |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
75 freq = ui.configint('profiling', 'freq', default=1000) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
76 filter_ = None |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
77 collapse_recursion = True |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
78 thread = flamegraph.ProfileThread(fp, 1.0 / freq, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
79 filter_, collapse_recursion) |
30995
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30950
diff
changeset
|
80 start_time = util.timer() |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
81 try: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
82 thread.start() |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
83 yield |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
84 finally: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
85 thread.stop() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
86 thread.join() |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
87 print('Collected %d stack frames (%d unique) in %2.2f seconds.' % ( |
30995
22fbca1d11ed
mercurial: switch to util.timer for all interval timings
Simon Farnsworth <simonfar@fb.com>
parents:
30950
diff
changeset
|
88 util.timer() - start_time, thread.num_frames(), |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
89 thread.num_frames(unique=True))) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
90 |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
91 @contextlib.contextmanager |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
92 def statprofile(ui, fp): |
30329
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
93 from . import statprof |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
94 |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
95 freq = ui.configint('profiling', 'freq', default=1000) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
96 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
|
97 # 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
|
98 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
|
99 statprof.reset(freq) |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
100 else: |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
101 ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq) |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
102 |
30329
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
103 statprof.start(mechanism='thread') |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
104 |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
105 try: |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
106 yield |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
107 finally: |
30329
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
108 data = statprof.stop() |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
109 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
110 profformat = ui.config('profiling', 'statformat', 'hotpath') |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
111 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
112 formats = { |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
113 'byline': statprof.DisplayFormats.ByLine, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
114 'bymethod': statprof.DisplayFormats.ByMethod, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
115 'hotpath': statprof.DisplayFormats.Hotpath, |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
116 'json': statprof.DisplayFormats.Json, |
30950
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
117 'chrome': statprof.DisplayFormats.Chrome, |
30329
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
118 } |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
119 |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
120 if profformat in formats: |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
121 displayformat = formats[profformat] |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
122 else: |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
123 ui.warn(_('unknown profiler output format: %s\n') % profformat) |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
124 displayformat = statprof.DisplayFormats.Hotpath |
faf1b8923da2
profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29796
diff
changeset
|
125 |
30950
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
126 kwargs = {} |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
127 |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
128 def fraction(s): |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
129 if s.endswith('%'): |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
130 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
|
131 else: |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
132 v = float(s) |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
133 if 0 <= v <= 1: |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
134 return v |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
135 raise ValueError(s) |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
136 |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
137 if profformat == 'chrome': |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
138 showmin = ui.configwith(fraction, 'profiling', 'showmin', 0.005) |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
139 showmax = ui.configwith(fraction, 'profiling', 'showmax', 0.999) |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
140 kwargs.update(minthreshold=showmin, maxthreshold=showmax) |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
141 |
517bc1cd7033
profiling: add statprof support for Chrome trace viewer rendering
Bryan O'Sullivan <bryano@fb.com>
parents:
30820
diff
changeset
|
142 statprof.display(fp, data=data, format=displayformat, **kwargs) |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
143 |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
144 class profile(object): |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
145 """Start profiling. |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
146 |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
147 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
|
148 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
|
149 """ |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
150 def __init__(self, ui): |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
151 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
|
152 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
|
153 self._fp = None |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
154 self._profiler = None |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
155 |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
156 def __enter__(self): |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
157 profiler = encoding.environ.get('HGPROF') |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
158 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
|
159 if profiler is None: |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
160 profiler = self._ui.config('profiling', 'type', default='stat') |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
161 if profiler not in ('ls', 'stat', 'flame'): |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
162 # 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
|
163 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
|
164 if proffn is None: |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
165 self._ui.warn(_("unrecognized profiler '%s' - ignored\n") |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
166 % profiler) |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
167 profiler = 'stat' |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
168 |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
169 self._output = self._ui.config('profiling', 'output') |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
170 |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
171 if self._output == 'blackbox': |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
172 self._fp = util.stringio() |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
173 elif self._output: |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
174 path = self._ui.expandpath(self._output) |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
175 self._fp = open(path, 'wb') |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
176 else: |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
177 self._fp = self._ui.ferr |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
178 |
32455
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
179 if proffn is not None: |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
180 pass |
f40dc6f7c12f
profiling: allow loading profiling extension before everything else
Jun Wu <quark@fb.com>
parents:
30995
diff
changeset
|
181 elif profiler == 'ls': |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
182 proffn = lsprofile |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
183 elif profiler == 'flame': |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
184 proffn = flameprofile |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
185 else: |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
186 proffn = statprofile |
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
187 |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
188 self._profiler = proffn(self._ui, self._fp) |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
189 self._profiler.__enter__() |
29794
5d44197c208b
profiling: make profiling functions context managers (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29792
diff
changeset
|
190 |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
191 def __exit__(self, exception_type, exception_value, traceback): |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
192 if self._profiler is None: |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
193 return |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
194 self._profiler.__exit__(exception_type, exception_value, traceback) |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
195 if self._output: |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
196 if self._output == 'blackbox': |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
197 val = 'Profile:\n%s' % self._fp.getvalue() |
29792
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
198 # ui.log treats the input as a format string, |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
199 # so we need to escape any % signs. |
2654a0aac80d
profiling: move profiling code from dispatch.py (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
200 val = val.replace('%', '%%') |
32803
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
201 self._ui.log('profile', val) |
4483696dacee
profile: upgrade the "profile" context manager to a full class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
32455
diff
changeset
|
202 self._fp.close() |
29795
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
203 |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
204 @contextlib.contextmanager |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
205 def maybeprofile(ui): |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
206 """Profile if enabled, else do nothing. |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
207 |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
208 This context manager can be used to optionally profile if profiling |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
209 is enabled. Otherwise, it does nothing. |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
210 |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
211 The purpose of this context manager is to make calling code simpler: |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
212 just use a single code path for calling into code you may want to profile |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
213 and this function determines whether to start profiling. |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
214 """ |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
215 if ui.configbool('profiling', 'enabled'): |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
216 with profile(ui): |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
217 yield |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
218 else: |
e3501546f7e4
profiling: add a context manager that no-ops if profiling isn't enabled
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29794
diff
changeset
|
219 yield |