source: benchmark/rmit.py@ bb9924c

ADT ast-experimental enum forall-pointer-decay new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since bb9924c was 6f27b67, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Could not get rmit.py working with the exception benchmark, but I got one improvement along the way.

  • Property mode set to 100755
File size: 6.0 KB
Line 
1#!/usr/bin/python3
2"""
3Python Script to implement R.M.I.T. testing : Randomized Multiple Interleaved Trials
4
5./rmit.py run COMMAND CANDIDATES
6-t trials
7-o option:values
8"""
9
10
11import argparse
12import datetime
13import itertools
14import json
15import os
16import random
17import re
18import subprocess
19import sys
20
21
22def parse_range(x):
23 result = []
24 for part in x.split(','):
25 if '-' in part:
26 a, b = part.split('-')
27 a, b = int(a), int(b)
28 result.extend(range(a, b + 1))
29 else:
30 a = int(part)
31 result.append(a)
32 return result
33
34class DependentOpt:
35 def __init__(self, key, value):
36 self.key = key
37 self.value = value
38 self.vars = re.findall("[a-zA-Z]", value)
39
40def parse_option(key, values):
41 try:
42 num = int(values)
43 return key, [num]
44 except:
45 pass
46
47 if re.search("^[0-9-,]+$", values):
48 values = parse_range(values)
49 return key, [v for v in values]
50 else:
51 return key, DependentOpt(key, values)
52
53def eval_one(fmt, vals):
54 orig = fmt
55 for k, v in vals:
56 fmt = fmt.replace(k, str(v))
57
58 if not re.search("^[0-9-/*+ ]+$", fmt):
59 print('ERROR: pattern option {} (interpreted as {}) could not be evaluated'.format(orig, fmt), file=sys.stderr)
60 sys.exit(1)
61
62 return eval(fmt)
63
64def eval_options(opts):
65 dependents = [d for d in opts.values() if type(d) is DependentOpt]
66 processed = []
67 nopts = []
68 for d in dependents:
69 processed.append(d.key)
70 lists = []
71 for dvar in d.vars:
72 if not dvar in opts.keys():
73 print('ERROR: extra pattern option {}:{} uses unknown key {}'.format(d.key,d.value,dvar), file=sys.stderr)
74 sys.exit(1)
75
76 lists.append([(dvar, o) for o in opts[dvar]])
77 processed.append(dvar)
78
79 kopt = []
80 for vals in list(itertools.product(*lists)):
81 res = ['-{}'.format(d.key), "{}".format(eval_one(d.value, vals))]
82 for k, v in vals:
83 res.extend(['-{}'.format(k), "{}".format(v)])
84 kopt.append(res)
85 nopts.append(kopt)
86
87
88 for k, vals in opts.items():
89 if k not in processed:
90 kopt = []
91 for v in vals:
92 kopt.append(['-{}'.format(k), "{}".format(v)])
93 nopts.append(kopt)
94
95 return nopts
96
97def actions_eta(actions):
98 time = 0
99 for a in actions:
100 i = 0
101 while i < len(a):
102 if a[i] == '-d':
103 i += 1
104 if i != len(a):
105 time += int(a[i])
106 i += 1
107 return time
108
109if __name__ == "__main__":
110 # ================================================================================
111 # parse command line arguments
112 formats = ['raw', 'csv', 'json']
113 parser = argparse.ArgumentParser(description='Python Script to implement R.M.I.T. testing : Randomized Multiple Interleaved Trials')
114 parser.add_argument('--list', help='List all the commands that would be run', action='store_true')
115 parser.add_argument('--file', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
116 parser.add_argument('--trials', help='Number of trials to run per combinaison', type=int, default=3)
117 parser.add_argument('command', metavar='command', type=str, nargs=1, help='the command prefix to run')
118 parser.add_argument('candidates', metavar='candidates', type=str, nargs='*', help='the candidate suffix to run')
119
120 try:
121 options, unknown = parser.parse_known_args()
122
123 options.option = []
124 while unknown:
125 key = unknown.pop(0)
126 val = unknown.pop(0)
127
128 if key[0] != '-':
129 raise ValueError
130
131 options.option.append((key[1:], val))
132
133 except:
134 print('ERROR: invalid arguments', file=sys.stderr)
135 parser.print_help(sys.stderr)
136 sys.exit(1)
137
138 # ================================================================================
139 # Identify the commands to run
140 command = './' + options.command[0]
141 if options.candidates:
142 commands = [command + "-" + c for c in options.candidates]
143 else:
144 commands = [command]
145 for c in commands:
146 if not os.path.isfile(c):
147 print('ERROR: invalid command {}, file does not exist'.format(c), file=sys.stderr)
148 sys.exit(1)
149
150 if not os.access(c, os.X_OK):
151 print('ERROR: invalid command {}, file not executable'.format(c), file=sys.stderr)
152 sys.exit(1)
153
154
155 # ================================================================================
156 # Identify the options to run
157 opts = dict([parse_option(k, v) for k, v in options.option])
158
159 # Evaluate the options (options can depend on the value of other options)
160 opts = eval_options(opts)
161
162 # ================================================================================
163 # Figure out all the combinations to run
164 actions = []
165 for p in itertools.product(range(options.trials), commands, *opts):
166 act = [p[1]]
167 for o in p[2:]:
168 act.extend(o)
169 actions.append(act)
170
171 # ================================================================================
172 # Figure out all the combinations to run
173 if options.list:
174 for a in actions:
175 print(" ".join(a))
176 sys.exit(0)
177
178
179 # ================================================================================
180 # Prepare to run
181
182 # find expected time
183 time = actions_eta(actions)
184 print("Running {} trials{}".format(len(actions), "" if time == 0 else " (expecting to take {})".format(str(datetime.timedelta(seconds=int(time)))) ))
185
186 random.shuffle(actions)
187
188 # ================================================================================
189 # Run
190 options.file.write("[")
191 first = True
192 for i, a in enumerate(actions):
193 sa = " ".join(a)
194 if first:
195 first = False
196 else:
197 options.file.write(",")
198 if options.file != sys.stdout:
199 print("{}/{} : {} \r".format(i, len(actions), sa), end = '')
200 fields = {}
201 with subprocess.Popen( a, stdout = subprocess.PIPE, stderr = subprocess.PIPE) as proc:
202 out, err = proc.communicate()
203 if proc.returncode != 0:
204 print("ERROR: command '{}' encountered error, returned code {}".format(sa, proc.returncode), file=sys.stderr)
205 print(err.decode("utf-8"))
206 sys.exit(1)
207 for s in out.decode("utf-8").splitlines():
208 match = re.search("^(.*):(.*)$", s)
209 if match:
210 fields[match.group(1).strip()] = float(match.group(2).strip().replace(',',''))
211
212 options.file.write(json.dumps([a[0][2:], sa, fields]))
213 options.file.flush()
214
215 options.file.write("]\n")
216
217 if options.file != sys.stdout:
218 print("Done ")
Note: See TracBrowser for help on using the repository browser.