Show More
@@ -0,0 +1,100 b'' | |||
|
1 | #!/usr/bin/env python | |
|
2 | # | |
|
3 | # hgperf - measure performance of Mercurial commands | |
|
4 | # | |
|
5 | # Copyright 2014 Matt Mackall <mpm@selenic.com> | |
|
6 | # | |
|
7 | # This software may be used and distributed according to the terms of the | |
|
8 | # GNU General Public License version 2 or any later version. | |
|
9 | ||
|
10 | '''measure performance of Mercurial commands | |
|
11 | ||
|
12 | Using ``hgperf`` instead of ``hg`` measures performance of the target | |
|
13 | Mercurial command. For example, the execution below measures | |
|
14 | performance of :hg:`heads --topo`:: | |
|
15 | ||
|
16 | $ hgperf heads --topo | |
|
17 | ||
|
18 | All command output via ``ui`` is suppressed, and just measurement | |
|
19 | result is displayed: see also "perf" extension in "contrib". | |
|
20 | ||
|
21 | Costs of processing before dispatching to the command function like | |
|
22 | below are not measured:: | |
|
23 | ||
|
24 | - parsing command line (e.g. option validity check) | |
|
25 | - reading configuration files in | |
|
26 | ||
|
27 | But ``pre-`` and ``post-`` hook invocation for the target command is | |
|
28 | measured, even though these are invoked before or after dispatching to | |
|
29 | the command function, because these may be required to repeat | |
|
30 | execution of the target command correctly. | |
|
31 | ''' | |
|
32 | ||
|
33 | import os | |
|
34 | import sys | |
|
35 | ||
|
36 | libdir = '@LIBDIR@' | |
|
37 | ||
|
38 | if libdir != '@' 'LIBDIR' '@': | |
|
39 | if not os.path.isabs(libdir): | |
|
40 | libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), | |
|
41 | libdir) | |
|
42 | libdir = os.path.abspath(libdir) | |
|
43 | sys.path.insert(0, libdir) | |
|
44 | ||
|
45 | # enable importing on demand to reduce startup time | |
|
46 | try: | |
|
47 | from mercurial import demandimport; demandimport.enable() | |
|
48 | except ImportError: | |
|
49 | import sys | |
|
50 | sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % | |
|
51 | ' '.join(sys.path)) | |
|
52 | sys.stderr.write("(check your install and PYTHONPATH)\n") | |
|
53 | sys.exit(-1) | |
|
54 | ||
|
55 | import mercurial.util | |
|
56 | import mercurial.dispatch | |
|
57 | ||
|
58 | import time | |
|
59 | ||
|
60 | def timer(func, title=None): | |
|
61 | results = [] | |
|
62 | begin = time.time() | |
|
63 | count = 0 | |
|
64 | while True: | |
|
65 | ostart = os.times() | |
|
66 | cstart = time.time() | |
|
67 | r = func() | |
|
68 | cstop = time.time() | |
|
69 | ostop = os.times() | |
|
70 | count += 1 | |
|
71 | a, b = ostart, ostop | |
|
72 | results.append((cstop - cstart, b[0] - a[0], b[1]-a[1])) | |
|
73 | if cstop - begin > 3 and count >= 100: | |
|
74 | break | |
|
75 | if cstop - begin > 10 and count >= 3: | |
|
76 | break | |
|
77 | if title: | |
|
78 | sys.stderr.write("! %s\n" % title) | |
|
79 | if r: | |
|
80 | sys.stderr.write("! result: %s\n" % r) | |
|
81 | m = min(results) | |
|
82 | sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n" | |
|
83 | % (m[0], m[1] + m[2], m[1], m[2], count)) | |
|
84 | ||
|
85 | orgruncommand = mercurial.dispatch.runcommand | |
|
86 | ||
|
87 | def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): | |
|
88 | ui.pushbuffer() | |
|
89 | lui.pushbuffer() | |
|
90 | timer(lambda : orgruncommand(lui, repo, cmd, fullargs, ui, | |
|
91 | options, d, cmdpats, cmdoptions)) | |
|
92 | ui.popbuffer() | |
|
93 | lui.popbuffer() | |
|
94 | ||
|
95 | mercurial.dispatch.runcommand = runcommand | |
|
96 | ||
|
97 | for fp in (sys.stdin, sys.stdout, sys.stderr): | |
|
98 | mercurial.util.setbinary(fp) | |
|
99 | ||
|
100 | mercurial.dispatch.run() |
General Comments 0
You need to be logged in to leave comments.
Login now