mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 23:38:50 +03:00
dispatch: add support for statprof as a profiler
This can be selected using the config variable profiling.type or the environment variable HGPROF ("ls" for the default, "stat" for statprof). The only tuneable is the frequency, profiling.freq, which defaults to 1000 Hz. If statprof is not available, a warning is printed.
This commit is contained in:
parent
af163e9811
commit
af2413c514
@ -687,14 +687,7 @@ def _dispatch(req):
|
||||
if repo and repo != req.repo:
|
||||
repo.close()
|
||||
|
||||
def _runcommand(ui, options, cmd, cmdfunc):
|
||||
def checkargs():
|
||||
try:
|
||||
return cmdfunc()
|
||||
except error.SignatureError:
|
||||
raise error.CommandError(cmd, _("invalid arguments"))
|
||||
|
||||
if options['profile']:
|
||||
def lsprofile(ui, func, fp):
|
||||
format = ui.config('profiling', 'format', default='text')
|
||||
field = ui.config('profiling', 'sort', default='inlinetime')
|
||||
climit = ui.configint('profiling', 'nested', default=5)
|
||||
@ -704,14 +697,6 @@ def _runcommand(ui, options, cmd, cmdfunc):
|
||||
" - Ignored\n") % format)
|
||||
format = 'text'
|
||||
|
||||
output = ui.config('profiling', 'output')
|
||||
|
||||
if output:
|
||||
path = ui.expandpath(output)
|
||||
ostream = open(path, 'wb')
|
||||
else:
|
||||
ostream = sys.stderr
|
||||
|
||||
try:
|
||||
from mercurial import lsprof
|
||||
except ImportError:
|
||||
@ -721,21 +706,70 @@ def _runcommand(ui, options, cmd, cmdfunc):
|
||||
p = lsprof.Profiler()
|
||||
p.enable(subcalls=True)
|
||||
try:
|
||||
return checkargs()
|
||||
return func()
|
||||
finally:
|
||||
p.disable()
|
||||
|
||||
if format == 'kcachegrind':
|
||||
import lsprofcalltree
|
||||
calltree = lsprofcalltree.KCacheGrind(p)
|
||||
calltree.output(ostream)
|
||||
calltree.output(fp)
|
||||
else:
|
||||
# format == 'text'
|
||||
stats = lsprof.Stats(p.getstats())
|
||||
stats.sort(field)
|
||||
stats.pprint(limit=30, file=ostream, climit=climit)
|
||||
stats.pprint(limit=30, file=fp, climit=climit)
|
||||
|
||||
def statprofile(ui, func, fp):
|
||||
try:
|
||||
import statprof
|
||||
except ImportError:
|
||||
raise util.Abort(_(
|
||||
'statprof not available - install using "easy_install statprof"'))
|
||||
|
||||
freq = ui.configint('profiling', 'freq', default=1000)
|
||||
if freq > 0:
|
||||
statprof.reset(freq)
|
||||
else:
|
||||
ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq)
|
||||
|
||||
statprof.start()
|
||||
try:
|
||||
return func()
|
||||
finally:
|
||||
statprof.stop()
|
||||
statprof.display(fp)
|
||||
|
||||
def _runcommand(ui, options, cmd, cmdfunc):
|
||||
def checkargs():
|
||||
try:
|
||||
return cmdfunc()
|
||||
except error.SignatureError:
|
||||
raise error.CommandError(cmd, _("invalid arguments"))
|
||||
|
||||
if options['profile']:
|
||||
profiler = os.getenv('HGPROF')
|
||||
if profiler is None:
|
||||
profiler = ui.config('profiling', 'type', default='ls')
|
||||
if profiler not in ('ls', 'stat'):
|
||||
ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
|
||||
profiler = 'ls'
|
||||
|
||||
output = ui.config('profiling', 'output')
|
||||
|
||||
if output:
|
||||
ostream.close()
|
||||
path = ui.expandpath(output)
|
||||
fp = open(path, 'wb')
|
||||
else:
|
||||
fp = sys.stderr
|
||||
|
||||
try:
|
||||
if profiler == 'ls':
|
||||
return lsprofile(ui, checkargs, fp)
|
||||
else:
|
||||
return statprofile(ui, checkargs, fp)
|
||||
finally:
|
||||
if output:
|
||||
fp.close()
|
||||
else:
|
||||
return checkargs()
|
||||
|
@ -938,14 +938,31 @@ information about working with phases.
|
||||
``profiling``
|
||||
"""""""""""""
|
||||
|
||||
Specifies profiling format and file output. In this section
|
||||
description, 'profiling data' stands for the raw data collected
|
||||
during profiling, while 'profiling report' stands for a statistical
|
||||
text report generated from the profiling data. The profiling is done
|
||||
using lsprof.
|
||||
Specifies profiling type, format, and file output. Two profilers are
|
||||
supported: an instrumenting profiler (named ``ls``), and a sampling
|
||||
profiler (named ``stat``).
|
||||
|
||||
In this section description, 'profiling data' stands for the raw data
|
||||
collected during profiling, while 'profiling report' stands for a
|
||||
statistical text report generated from the profiling data. The
|
||||
profiling is done using lsprof.
|
||||
|
||||
``type``
|
||||
The type of profiler to use.
|
||||
Default: ls.
|
||||
|
||||
``ls``
|
||||
Use Python's built-in instrumenting profiler. This profiler
|
||||
works on all platforms, but each line number it reports is the
|
||||
first line of a function. This restriction makes it difficult to
|
||||
identify the expensive parts of a non-trivial function.
|
||||
``stat``
|
||||
Use a third-party statistical profiler, statprof. This profiler
|
||||
currently runs only on Unix systems, and is most useful for
|
||||
profiling commands that run for longer than about 0.1 seconds.
|
||||
|
||||
``format``
|
||||
Profiling format.
|
||||
Profiling format. Specific to the ``ls`` instrumenting profiler.
|
||||
Default: text.
|
||||
|
||||
``text``
|
||||
@ -957,6 +974,10 @@ using lsprof.
|
||||
file, the generated file can directly be loaded into
|
||||
kcachegrind.
|
||||
|
||||
``frequency``
|
||||
Sampling frequency. Specific to the ``stat`` sampling profiler.
|
||||
Default: 1000.
|
||||
|
||||
``output``
|
||||
File path where profiling data or report should be saved. If the
|
||||
file exists, it is replaced. Default: None, data is printed on
|
||||
|
Loading…
Reference in New Issue
Block a user