hgperf
98 lines
| 3.0 KiB
| text/plain
|
TextLexer
/ contrib / hgperf
FUJIWARA Katsunori
|
r20839 | #!/usr/bin/env python | ||
# | ||||
# hgperf - measure performance of Mercurial commands | ||||
# | ||||
# Copyright 2014 Matt Mackall <mpm@selenic.com> | ||||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
'''measure performance of Mercurial commands | ||||
Using ``hgperf`` instead of ``hg`` measures performance of the target | ||||
Mercurial command. For example, the execution below measures | ||||
performance of :hg:`heads --topo`:: | ||||
$ hgperf heads --topo | ||||
All command output via ``ui`` is suppressed, and just measurement | ||||
result is displayed: see also "perf" extension in "contrib". | ||||
Costs of processing before dispatching to the command function like | ||||
below are not measured:: | ||||
- parsing command line (e.g. option validity check) | ||||
- reading configuration files in | ||||
But ``pre-`` and ``post-`` hook invocation for the target command is | ||||
measured, even though these are invoked before or after dispatching to | ||||
the command function, because these may be required to repeat | ||||
execution of the target command correctly. | ||||
''' | ||||
import os | ||||
import sys | ||||
libdir = '@LIBDIR@' | ||||
if libdir != '@' 'LIBDIR' '@': | ||||
if not os.path.isabs(libdir): | ||||
libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), | ||||
libdir) | ||||
libdir = os.path.abspath(libdir) | ||||
sys.path.insert(0, libdir) | ||||
# enable importing on demand to reduce startup time | ||||
try: | ||||
from mercurial import demandimport; demandimport.enable() | ||||
except ImportError: | ||||
import sys | ||||
sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % | ||||
' '.join(sys.path)) | ||||
sys.stderr.write("(check your install and PYTHONPATH)\n") | ||||
sys.exit(-1) | ||||
import mercurial.util | ||||
import mercurial.dispatch | ||||
def timer(func, title=None): | ||||
results = [] | ||||
Simon Farnsworth
|
r30975 | begin = mercurial.util.timer() | ||
FUJIWARA Katsunori
|
r20839 | count = 0 | ||
while True: | ||||
ostart = os.times() | ||||
Simon Farnsworth
|
r30975 | cstart = mercurial.util.timer() | ||
FUJIWARA Katsunori
|
r20839 | r = func() | ||
Simon Farnsworth
|
r30975 | cstop = mercurial.util.timer() | ||
FUJIWARA Katsunori
|
r20839 | ostop = os.times() | ||
count += 1 | ||||
a, b = ostart, ostop | ||||
results.append((cstop - cstart, b[0] - a[0], b[1]-a[1])) | ||||
if cstop - begin > 3 and count >= 100: | ||||
break | ||||
if cstop - begin > 10 and count >= 3: | ||||
break | ||||
if title: | ||||
sys.stderr.write("! %s\n" % title) | ||||
if r: | ||||
sys.stderr.write("! result: %s\n" % r) | ||||
m = min(results) | ||||
sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n" | ||||
% (m[0], m[1] + m[2], m[1], m[2], count)) | ||||
orgruncommand = mercurial.dispatch.runcommand | ||||
def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): | ||||
ui.pushbuffer() | ||||
lui.pushbuffer() | ||||
timer(lambda : orgruncommand(lui, repo, cmd, fullargs, ui, | ||||
options, d, cmdpats, cmdoptions)) | ||||
ui.popbuffer() | ||||
lui.popbuffer() | ||||
mercurial.dispatch.runcommand = runcommand | ||||
for fp in (sys.stdin, sys.stdout, sys.stderr): | ||||
mercurial.util.setbinary(fp) | ||||
mercurial.dispatch.run() | ||||