comparison mercurial/profiling.py @ 32455:f40dc6f7c12f

profiling: allow loading profiling extension before everything else 6d642ecf1a89 makes profiler start early without loading extensions. That makes it impossible for an extension to add customized profilers. This patch adds a special case: if a profiler is not found but an extension with the same name could be loaded, load that extension first, and expect it to have a "profile" contextmanager method. This allows customized profilers and extension setup time is still profiled.
author Jun Wu <quark@fb.com>
date Mon, 22 May 2017 01:17:49 -0700
parents 22fbca1d11ed
children 4483696dacee
comparison
equal deleted inserted replaced
32454:9a3e88d4a030 32455:f40dc6f7c12f
11 11
12 from .i18n import _ 12 from .i18n import _
13 from . import ( 13 from . import (
14 encoding, 14 encoding,
15 error, 15 error,
16 extensions,
16 util, 17 util,
17 ) 18 )
19
20 def _loadprofiler(ui, profiler):
21 """load profiler extension. return profile method, or None on failure"""
22 extname = profiler
23 extensions.loadall(ui, whitelist=[extname])
24 try:
25 mod = extensions.find(extname)
26 except KeyError:
27 return None
28 else:
29 return getattr(mod, 'profile', None)
18 30
19 @contextlib.contextmanager 31 @contextlib.contextmanager
20 def lsprofile(ui, fp): 32 def lsprofile(ui, fp):
21 format = ui.config('profiling', 'format', default='text') 33 format = ui.config('profiling', 'format', default='text')
22 field = ui.config('profiling', 'sort', default='inlinetime') 34 field = ui.config('profiling', 'sort', default='inlinetime')
135 147
136 Profiling is active when the context manager is active. When the context 148 Profiling is active when the context manager is active. When the context
137 manager exits, profiling results will be written to the configured output. 149 manager exits, profiling results will be written to the configured output.
138 """ 150 """
139 profiler = encoding.environ.get('HGPROF') 151 profiler = encoding.environ.get('HGPROF')
152 proffn = None
140 if profiler is None: 153 if profiler is None:
141 profiler = ui.config('profiling', 'type', default='stat') 154 profiler = ui.config('profiling', 'type', default='stat')
142 if profiler not in ('ls', 'stat', 'flame'): 155 if profiler not in ('ls', 'stat', 'flame'):
143 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler) 156 # try load profiler from extension with the same name
144 profiler = 'stat' 157 proffn = _loadprofiler(ui, profiler)
158 if proffn is None:
159 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
160 profiler = 'stat'
145 161
146 output = ui.config('profiling', 'output') 162 output = ui.config('profiling', 'output')
147 163
148 if output == 'blackbox': 164 if output == 'blackbox':
149 fp = util.stringio() 165 fp = util.stringio()
152 fp = open(path, 'wb') 168 fp = open(path, 'wb')
153 else: 169 else:
154 fp = ui.ferr 170 fp = ui.ferr
155 171
156 try: 172 try:
157 if profiler == 'ls': 173 if proffn is not None:
174 pass
175 elif profiler == 'ls':
158 proffn = lsprofile 176 proffn = lsprofile
159 elif profiler == 'flame': 177 elif profiler == 'flame':
160 proffn = flameprofile 178 proffn = flameprofile
161 else: 179 else:
162 proffn = statprofile 180 proffn = statprofile