source: benchmark/rmit.py @ 9d264e18

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 9d264e18 was 883c4d9, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

rmit.py script no prints json by default.
Also it supports json now.

  • Property mode set to 100755
File size: 6.9 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(opt):
41        match = re.search("^(.*):(.*)$", opt)
42        if not match :
43                print('ERROR: extra options should match pattern .*:.*, got {}'.format(opt), file=sys.stderr)
44                sys.exit(1)
45
46        key    = match.group(1)
47        values = match.group(2)
48
49        try:
50                num = int(values)
51                return key, [num]
52        except:
53                pass
54
55        if re.search("^[0-9-,]+$", values):
56                values = parse_range(values)
57                return key, [v for v in values]
58        else:
59                return key, DependentOpt(key, values)
60
61def eval_one(fmt, vals):
62        orig = fmt
63        for k, v in vals:
64                fmt = fmt.replace(k, str(v))
65
66        if not re.search("^[0-9-/*+ ]+$", fmt):
67                print('ERROR: pattern option {} (interpreted as {}) could not be evaluated'.format(orig, fmt), file=sys.stderr)
68                sys.exit(1)
69
70        return eval(fmt)
71
72def eval_options(opts):
73        dependents = [d for d in opts.values() if type(d) is DependentOpt]
74        processed = []
75        nopts = []
76        for d in dependents:
77                processed.append(d.key)
78                lists = []
79                for dvar in d.vars:
80                        if not dvar in opts.keys():
81                                print('ERROR: extra pattern option {}:{} uses unknown key {}'.format(d.key,d.value,dvar), file=sys.stderr)
82                                sys.exit(1)
83
84                        lists.append([(dvar, o) for o in opts[dvar]])
85                        processed.append(dvar)
86
87                kopt = []
88                for vals in list(itertools.product(*lists)):
89                        res = ['-{}'.format(d.key), "{}".format(eval_one(d.value, vals))]
90                        for k, v in vals:
91                                res.extend(['-{}'.format(k), "{}".format(v)])
92                        kopt.append(res)
93                nopts.append(kopt)
94
95
96        for k, vals in opts.items():
97                if k not in processed:
98                        kopt = []
99                        for v in vals:
100                                kopt.append(['-{}'.format(k), "{}".format(v)])
101                        nopts.append(kopt)
102
103        return nopts
104
105def actions_eta(actions):
106        time = 0
107        for a in actions:
108                i = 0
109                while i < len(a):
110                        if a[i] == '-d':
111                                i += 1
112                                if i != len(a):
113                                        time += int(a[i])
114                        i += 1
115        return time
116
117if __name__ == "__main__":
118        # ================================================================================
119        # parse command line arguments
120        formats = ['raw', 'csv', 'json']
121        parser = argparse.ArgumentParser(description='Python Script to implement R.M.I.T. testing : Randomized Multiple Interleaved Trials')
122        parser.add_argument('--list', help='List all the commands that would be run', action='store_true')
123        parser.add_argument('--format', help='How to print the result', choices=formats, default='json')
124        parser.add_argument('--file', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
125        parser.add_argument('-t', '--trials', help='Number of trials to run per combinaison', type=int, default=3)
126        parser.add_argument('-o','--option',action='append')
127        parser.add_argument('command', metavar='command', type=str, nargs=1, help='the command prefix to run')
128        parser.add_argument('candidates', metavar='candidates', type=str, nargs='*', help='the candidate suffix to run')
129
130        try:
131                options =  parser.parse_args()
132        except:
133                print('ERROR: invalid arguments', file=sys.stderr)
134                parser.print_help(sys.stderr)
135                sys.exit(1)
136
137        # ================================================================================
138        # Identify the commands to run
139        commands = ["./" + options.command[0] + "-" + c for c in options.candidates]
140        for c in commands:
141                if not os.path.isfile(c):
142                        print('ERROR: invalid command {}, file does not exist'.format(c), file=sys.stderr)
143                        sys.exit(1)
144
145                if not os.access(c, os.X_OK):
146                        print('ERROR: invalid command {}, file not executable'.format(c), file=sys.stderr)
147                        sys.exit(1)
148
149
150        # ================================================================================
151        # Identify the options to run
152        opts = dict([parse_option(o) for o in options.option])
153
154        # Evaluate the options (options can depend on the value of other options)
155        opts = eval_options(opts)
156
157        # ================================================================================
158        # Figure out all the combinations to run
159        actions = []
160        for p in itertools.product(range(options.trials), commands, *opts):
161                act = [p[1]]
162                for o in p[2:]:
163                        act.extend(o)
164                actions.append(act)
165
166        # ================================================================================
167        # Figure out all the combinations to run
168        if options.list:
169                for a in actions:
170                        print(" ".join(a))
171                sys.exit(0)
172
173
174        # ================================================================================
175        # Prepare to run
176
177        # find expected time
178        time = actions_eta(actions)
179        print("Running {} trials{}".format(len(actions), "" if time == 0 else " (expecting to take {}".format(str(datetime.timedelta(seconds=int(time)))) ))
180
181        random.shuffle(actions)
182        result = []
183
184        # ================================================================================
185        # Run
186        for i, a in enumerate(actions):
187                sa = " ".join(a)
188                print("{}/{} : {}          \r".format(i, len(actions), sa), end = '')
189                fields = {}
190                with subprocess.Popen( a, stdout  = subprocess.PIPE, stderr  = subprocess.PIPE) as proc:
191                        out, err = proc.communicate()
192                        if proc.returncode != 0:
193                                print("ERROR: command '{}' encountered error, returned code {}".format(sa, proc.returncode), file=sys.stderr)
194                                print(err.decode("utf-8"))
195                                sys.exit(1)
196                        for s in out.decode("utf-8").splitlines():
197                                match = re.search("^(.*):(.*)$", s)
198                                if match:
199                                        fields[match.group(1).strip()] = float(match.group(2).strip().replace(',',''))
200
201                result.append([a[0][2:], sa, fields])
202
203        print("Done                                                                                ")
204
205        # ================================================================================
206        # Print raw
207        if options.format == 'raw':
208                for r in result:
209                        print(r, file=options.file)
210                sys.exit(0)
211
212        # ================================================================================
213        # Print json
214        if options.format == 'json':
215                json.dump(result, options.file)
216                sys.exit(0)
217
218        # ================================================================================
219        # Print csv
220        if options.format == 'csv':
221                # Clean result
222                headers = ["series", "command"]
223                data = []
224                first = True
225                for r in result:
226                        if first:
227                                first = False
228                                headers.extend(r[2].keys())
229                        else :
230                                pass
231
232                        d = [r[0], r[1]]
233                        for k in headers[2:]:
234                                try:
235                                        d.append(r[2][k])
236                                except:
237                                        d.append(0.0)
238
239                        data.append(d)
240
241                # Print csv
242                print(",\t".join(headers), file=options.file)
243                for d in data:
244                        print(",\t".join(["{}".format(dd) for dd in d]), file=options.file)
245                sys.exit(0)
Note: See TracBrowser for help on using the repository browser.