##// END OF EJS Templates
revsetbenchmarks: improve error output in case of failure...
Pierre-Yves David -
r25529:3e80691d default
parent child Browse files
Show More
@@ -1,152 +1,156 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 # Measure the performance of a list of revsets against multiple revisions
3 # Measure the performance of a list of revsets against multiple revisions
4 # defined by parameter. Checkout one by one and run perfrevset with every
4 # defined by parameter. Checkout one by one and run perfrevset with every
5 # revset in the list to benchmark its performance.
5 # revset in the list to benchmark its performance.
6 #
6 #
7 # - First argument is a revset of mercurial own repo to runs against.
7 # - First argument is a revset of mercurial own repo to runs against.
8 # - Second argument is the file from which the revset array will be taken
8 # - Second argument is the file from which the revset array will be taken
9 # If second argument is omitted read it from standard input
9 # If second argument is omitted read it from standard input
10 #
10 #
11 # You should run this from the root of your mercurial repository.
11 # You should run this from the root of your mercurial repository.
12 #
12 #
13 # This script also does one run of the current version of mercurial installed
13 # This script also does one run of the current version of mercurial installed
14 # to compare performance.
14 # to compare performance.
15
15
16 import sys
16 import sys
17 import os
17 import os
18 from subprocess import check_call, Popen, CalledProcessError, STDOUT, PIPE
18 from subprocess import check_call, Popen, CalledProcessError, STDOUT, PIPE
19 # cannot use argparse, python 2.7 only
19 # cannot use argparse, python 2.7 only
20 from optparse import OptionParser
20 from optparse import OptionParser
21
21
22 def check_output(*args, **kwargs):
22 def check_output(*args, **kwargs):
23 kwargs.setdefault('stderr', PIPE)
23 kwargs.setdefault('stderr', PIPE)
24 kwargs.setdefault('stdout', PIPE)
24 kwargs.setdefault('stdout', PIPE)
25 proc = Popen(*args, **kwargs)
25 proc = Popen(*args, **kwargs)
26 output, error = proc.communicate()
26 output, error = proc.communicate()
27 if proc.returncode != 0:
27 if proc.returncode != 0:
28 raise CalledProcessError(proc.returncode, ' '.join(args[0]))
28 raise CalledProcessError(proc.returncode, ' '.join(args[0]))
29 return output
29 return output
30
30
31 def update(rev):
31 def update(rev):
32 """update the repo to a revision"""
32 """update the repo to a revision"""
33 try:
33 try:
34 check_call(['hg', 'update', '--quiet', '--check', str(rev)])
34 check_call(['hg', 'update', '--quiet', '--check', str(rev)])
35 except CalledProcessError, exc:
35 except CalledProcessError, exc:
36 print >> sys.stderr, 'update to revision %s failed, aborting' % rev
36 print >> sys.stderr, 'update to revision %s failed, aborting' % rev
37 sys.exit(exc.returncode)
37 sys.exit(exc.returncode)
38
38
39
39
40 def hg(cmd, repo=None):
40 def hg(cmd, repo=None):
41 """run a mercurial command
41 """run a mercurial command
42
42
43 <cmd> is the list of command + argument,
43 <cmd> is the list of command + argument,
44 <repo> is an optional repository path to run this command in."""
44 <repo> is an optional repository path to run this command in."""
45 fullcmd = ['./hg']
45 fullcmd = ['./hg']
46 if repo is not None:
46 if repo is not None:
47 fullcmd += ['-R', repo]
47 fullcmd += ['-R', repo]
48 fullcmd += ['--config',
48 fullcmd += ['--config',
49 'extensions.perf=' + os.path.join(contribdir, 'perf.py')]
49 'extensions.perf=' + os.path.join(contribdir, 'perf.py')]
50 fullcmd += cmd
50 fullcmd += cmd
51 return check_output(fullcmd, stderr=STDOUT)
51 return check_output(fullcmd, stderr=STDOUT)
52
52
53 def perf(revset, target=None):
53 def perf(revset, target=None):
54 """run benchmark for this very revset"""
54 """run benchmark for this very revset"""
55 try:
55 try:
56 output = hg(['perfrevset', revset], repo=target)
56 output = hg(['perfrevset', revset], repo=target)
57 output = output.lstrip('!') # remove useless ! in this context
57 output = output.lstrip('!') # remove useless ! in this context
58 return output.strip()
58 return output.strip()
59 except CalledProcessError, exc:
59 except CalledProcessError, exc:
60 print >> sys.stderr, 'abort: cannot run revset benchmark'
60 print >> sys.stderr, 'abort: cannot run revset benchmark: %s' % exc.cmd
61 if exc.output is None:
62 print >> sys.stderr, '(no ouput)'
63 else:
64 print >> sys.stderr, exc.output
61 sys.exit(exc.returncode)
65 sys.exit(exc.returncode)
62
66
63 def printrevision(rev):
67 def printrevision(rev):
64 """print data about a revision"""
68 """print data about a revision"""
65 sys.stdout.write("Revision: ")
69 sys.stdout.write("Revision: ")
66 sys.stdout.flush()
70 sys.stdout.flush()
67 check_call(['hg', 'log', '--rev', str(rev), '--template',
71 check_call(['hg', 'log', '--rev', str(rev), '--template',
68 '{desc|firstline}\n'])
72 '{desc|firstline}\n'])
69
73
70 def getrevs(spec):
74 def getrevs(spec):
71 """get the list of rev matched by a revset"""
75 """get the list of rev matched by a revset"""
72 try:
76 try:
73 out = check_output(['hg', 'log', '--template={rev}\n', '--rev', spec])
77 out = check_output(['hg', 'log', '--template={rev}\n', '--rev', spec])
74 except CalledProcessError, exc:
78 except CalledProcessError, exc:
75 print >> sys.stderr, "abort, can't get revision from %s" % spec
79 print >> sys.stderr, "abort, can't get revision from %s" % spec
76 sys.exit(exc.returncode)
80 sys.exit(exc.returncode)
77 return [r for r in out.split() if r]
81 return [r for r in out.split() if r]
78
82
79
83
80 parser = OptionParser(usage="usage: %prog [options] <revs>")
84 parser = OptionParser(usage="usage: %prog [options] <revs>")
81 parser.add_option("-f", "--file",
85 parser.add_option("-f", "--file",
82 help="read revset from FILE (stdin if omitted)",
86 help="read revset from FILE (stdin if omitted)",
83 metavar="FILE")
87 metavar="FILE")
84 parser.add_option("-R", "--repo",
88 parser.add_option("-R", "--repo",
85 help="run benchmark on REPO", metavar="REPO")
89 help="run benchmark on REPO", metavar="REPO")
86
90
87 (options, args) = parser.parse_args()
91 (options, args) = parser.parse_args()
88
92
89 if len(sys.argv) < 2:
93 if len(sys.argv) < 2:
90 parser.print_help()
94 parser.print_help()
91 sys.exit(255)
95 sys.exit(255)
92
96
93 # the directory where both this script and the perf.py extension live.
97 # the directory where both this script and the perf.py extension live.
94 contribdir = os.path.dirname(__file__)
98 contribdir = os.path.dirname(__file__)
95
99
96 target_rev = args[0]
100 target_rev = args[0]
97
101
98 revsetsfile = sys.stdin
102 revsetsfile = sys.stdin
99 if options.file:
103 if options.file:
100 revsetsfile = open(options.file)
104 revsetsfile = open(options.file)
101
105
102 revsets = [l.strip() for l in revsetsfile if not l.startswith('#')]
106 revsets = [l.strip() for l in revsetsfile if not l.startswith('#')]
103
107
104 print "Revsets to benchmark"
108 print "Revsets to benchmark"
105 print "----------------------------"
109 print "----------------------------"
106
110
107 for idx, rset in enumerate(revsets):
111 for idx, rset in enumerate(revsets):
108 print "%i) %s" % (idx, rset)
112 print "%i) %s" % (idx, rset)
109
113
110 print "----------------------------"
114 print "----------------------------"
111 print
115 print
112
116
113
117
114 revs = getrevs(target_rev)
118 revs = getrevs(target_rev)
115
119
116 results = []
120 results = []
117 for r in revs:
121 for r in revs:
118 print "----------------------------"
122 print "----------------------------"
119 printrevision(r)
123 printrevision(r)
120 print "----------------------------"
124 print "----------------------------"
121 update(r)
125 update(r)
122 res = []
126 res = []
123 results.append(res)
127 results.append(res)
124 for idx, rset in enumerate(revsets):
128 for idx, rset in enumerate(revsets):
125 data = perf(rset, target=options.repo)
129 data = perf(rset, target=options.repo)
126 res.append(data)
130 res.append(data)
127 print "%i)" % idx, data
131 print "%i)" % idx, data
128 sys.stdout.flush()
132 sys.stdout.flush()
129 print "----------------------------"
133 print "----------------------------"
130
134
131
135
132 print """
136 print """
133
137
134 Result by revset
138 Result by revset
135 ================
139 ================
136 """
140 """
137
141
138 print 'Revision:', revs
142 print 'Revision:', revs
139 for idx, rev in enumerate(revs):
143 for idx, rev in enumerate(revs):
140 sys.stdout.write('%i) ' % idx)
144 sys.stdout.write('%i) ' % idx)
141 sys.stdout.flush()
145 sys.stdout.flush()
142 printrevision(rev)
146 printrevision(rev)
143
147
144 print
148 print
145 print
149 print
146
150
147 for ridx, rset in enumerate(revsets):
151 for ridx, rset in enumerate(revsets):
148
152
149 print "revset #%i: %s" % (ridx, rset)
153 print "revset #%i: %s" % (ridx, rset)
150 for idx, data in enumerate(results):
154 for idx, data in enumerate(results):
151 print '%i) %s' % (idx, data[ridx])
155 print '%i) %s' % (idx, data[ridx])
152 print
156 print
General Comments 0
You need to be logged in to leave comments. Login now