blob: 2ad8f198e95ad0b541d4388bd0ac886114e1e6fc [file] [log] [blame]
koder aka kdanilov4af80852015-02-01 23:36:38 +02001import re
2import os
3import sys
4import stat
5import time
6import json
koder aka kdanilove21d7472015-02-14 19:02:04 -08007import Queue
koder aka kdanilov4af80852015-02-01 23:36:38 +02008import os.path
9import argparse
10import warnings
koder aka kdanilove21d7472015-02-14 19:02:04 -080011import threading
koder aka kdanilov4af80852015-02-01 23:36:38 +020012import subprocess
13
14
15class BenchmarkOption(object):
16 def __init__(self, concurence, iodepth, action, blocksize, size):
17 self.iodepth = iodepth
18 self.action = action
19 self.blocksize = blocksize
20 self.concurence = concurence
21 self.size = size
22 self.direct_io = False
23 self.use_hight_io_priority = True
24 self.sync = False
25
26
koder aka kdanilov98615bf2015-02-02 00:59:07 +020027def which(program):
28 def is_exe(fpath):
29 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
30
31 fpath, fname = os.path.split(program)
32 if fpath:
33 if is_exe(program):
34 return program
35 else:
36 for path in os.environ["PATH"].split(os.pathsep):
37 path = path.strip('"')
38 exe_file = os.path.join(path, program)
39 if is_exe(exe_file):
40 return exe_file
41
42 return None
43
44
45# ------------------------------ IOZONE SUPPORT ------------------------------
46
47
koder aka kdanilov4af80852015-02-01 23:36:38 +020048class IOZoneParser(object):
49 "class to parse iozone results"
50
51 start_tests = re.compile(r"^\s+KB\s+reclen\s+")
52 resuts = re.compile(r"[\s0-9]+")
53 mt_iozone_re = re.compile(r"\s+Children see throughput " +
54 r"for\s+\d+\s+(?P<cmd>.*?)\s+=\s+" +
55 r"(?P<perf>[\d.]+)\s+KB/sec")
56
57 cmap = {'initial writers': 'write',
58 'rewriters': 'rewrite',
59 'initial readers': 'read',
60 're-readers': 'reread',
61 'random readers': 'random read',
koder aka kdanilov7dec9df2015-02-15 21:35:19 -080062 'random writers': 'random write',
63 'readers': 'read'}
koder aka kdanilov4af80852015-02-01 23:36:38 +020064
65 string1 = " " + \
66 " random random " + \
67 "bkwd record stride "
68
69 string2 = "KB reclen write rewrite " + \
70 "read reread read write " + \
71 "read rewrite read fwrite frewrite fread freread"
72
73 @classmethod
74 def apply_parts(cls, parts, string, sep=' \t\n'):
75 add_offset = 0
76 for part in parts:
77 _, start, stop = part
78 start += add_offset
79 add_offset = 0
80
81 # condition splited to make pylint happy
82 while stop + add_offset < len(string):
83
84 # condition splited to make pylint happy
85 if not (string[stop + add_offset] not in sep):
86 break
87
88 add_offset += 1
89
90 yield part, string[start:stop + add_offset]
91
92 @classmethod
93 def make_positions(cls):
94 items = [i for i in cls.string2.split() if i]
95
96 pos = 0
97 cls.positions = []
98
99 for item in items:
100 npos = cls.string2.index(item, 0 if pos == 0 else pos + 1)
101 cls.positions.append([item, pos, npos + len(item)])
102 pos = npos + len(item)
103
104 for itm, val in cls.apply_parts(cls.positions, cls.string1):
105 if val.strip():
106 itm[0] = val.strip() + " " + itm[0]
107
108 @classmethod
109 def parse_iozone_res(cls, res, mthreads=False):
110 parsed_res = None
111
112 sres = res.split('\n')
113
114 if not mthreads:
115 for pos, line in enumerate(sres[1:]):
116 if line.strip() == cls.string2 and \
117 sres[pos].strip() == cls.string1.strip():
118 add_pos = line.index(cls.string2)
119 parsed_res = {}
120
121 npos = [(name, start + add_pos, stop + add_pos)
122 for name, start, stop in cls.positions]
123
124 for itm, res in cls.apply_parts(npos, sres[pos + 2]):
125 if res.strip() != '':
126 parsed_res[itm[0]] = int(res.strip())
127
128 del parsed_res['KB']
129 del parsed_res['reclen']
130 else:
131 parsed_res = {}
132 for line in sres:
133 rr = cls.mt_iozone_re.match(line)
134 if rr is not None:
135 cmd = rr.group('cmd')
136 key = cls.cmap.get(cmd, cmd)
137 perf = int(float(rr.group('perf')))
138 parsed_res[key] = perf
139 return parsed_res
140
141
koder aka kdanilov4af80852015-02-01 23:36:38 +0200142IOZoneParser.make_positions()
143
144
koder aka kdanilov3f356262015-02-13 08:06:14 -0800145def iozone_do_prepare(params, filename, pattern_base):
koder aka kdanilov4af80852015-02-01 23:36:38 +0200146 all_files = []
147 threads = int(params.concurence)
148 if 1 != threads:
koder aka kdanilov3f356262015-02-13 08:06:14 -0800149 filename = filename + "_{0}"
150 all_files.extend(filename .format(i) for i in range(threads))
koder aka kdanilov4af80852015-02-01 23:36:38 +0200151 else:
koder aka kdanilov4af80852015-02-01 23:36:38 +0200152 all_files.append(filename)
153
154 bsz = 1024 if params.size > 1024 else params.size
155 if params.size % bsz != 0:
156 fsz = (params.size // bsz + 1) * bsz
157 else:
158 fsz = params.size
159
160 for fname in all_files:
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200161 with open(fname, "wb") as fd:
162 if fsz > 1024:
koder aka kdanilov3f356262015-02-13 08:06:14 -0800163 pattern = pattern_base * 1024 * 1024
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200164 for _ in range(int(fsz / 1024) + 1):
165 fd.write(pattern)
166 else:
koder aka kdanilov3f356262015-02-13 08:06:14 -0800167 fd.write(pattern_base * 1024 * fsz)
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200168 fd.flush()
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800169 return all_files
170
171
172VERIFY_PATTERN = "\x6d"
173
174
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800175def prepare_iozone(params, filename):
176 return iozone_do_prepare(params, filename, VERIFY_PATTERN)
177
178
179def do_run_iozone(params, timeout, all_files,
180 iozone_path='iozone',
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800181 microsecond_mode=False,
182 prepare_only=False):
183
184 cmd = [iozone_path, "-V", str(ord(VERIFY_PATTERN))]
185
186 if params.sync:
187 cmd.append('-o')
188
189 if params.direct_io:
190 cmd.append('-I')
191
192 if microsecond_mode:
193 cmd.append('-N')
194
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800195 threads = int(params.concurence)
196 if 1 != threads:
197 cmd.extend(('-t', str(threads), '-F'))
198 cmd.extend(all_files)
199 else:
200 cmd.extend(('-f', all_files[0]))
koder aka kdanilov4af80852015-02-01 23:36:38 +0200201
202 cmd.append('-i')
203
204 if params.action == 'write':
205 cmd.append("0")
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200206 elif params.action == 'read':
207 cmd.append("1")
208 elif params.action == 'randwrite' or params.action == 'randread':
koder aka kdanilov4af80852015-02-01 23:36:38 +0200209 cmd.append("2")
210 else:
211 raise ValueError("Unknown action {0!r}".format(params.action))
212
213 cmd.extend(('-s', str(params.size)))
214 cmd.extend(('-r', str(params.blocksize)))
215
koder aka kdanilov78ba8952015-02-03 01:11:23 +0200216 # no retest
217 cmd.append('-+n')
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200218
koder aka kdanilov4af80852015-02-01 23:36:38 +0200219 raw_res = subprocess.check_output(cmd)
220
221 try:
222 parsed_res = IOZoneParser.parse_iozone_res(raw_res, threads > 1)
223
224 res = {}
225
226 if params.action == 'write':
227 res['bw_mean'] = parsed_res['write']
228 elif params.action == 'randwrite':
229 res['bw_mean'] = parsed_res['random write']
230 elif params.action == 'read':
231 res['bw_mean'] = parsed_res['read']
232 elif params.action == 'randread':
233 res['bw_mean'] = parsed_res['random read']
234 except:
koder aka kdanilov4af80852015-02-01 23:36:38 +0200235 raise
236
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200237 return res, " ".join(cmd)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200238
239
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800240def run_iozone(benchmark, binary_path, all_files,
koder aka kdanilov3f356262015-02-13 08:06:14 -0800241 timeout=None):
242
koder aka kdanilov4af80852015-02-01 23:36:38 +0200243 if timeout is not None:
244 benchmark.size = benchmark.blocksize * 50
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800245 res_time = do_run_iozone(benchmark, timeout, all_files,
246 iozone_path=binary_path,
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200247 microsecond_mode=True)[0]
koder aka kdanilov4af80852015-02-01 23:36:38 +0200248
249 size = (benchmark.blocksize * timeout * 1000000)
250 size /= res_time["bw_mean"]
251 size = (size // benchmark.blocksize + 1) * benchmark.blocksize
252 benchmark.size = size
253
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800254 return do_run_iozone(benchmark, timeout, all_files,
255 iozone_path=binary_path)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200256
257
koder aka kdanilov4af80852015-02-01 23:36:38 +0200258def install_iozone_package():
259 if which('iozone'):
260 return
261
262 is_redhat = os.path.exists('/etc/centos-release')
263 is_redhat = is_redhat or os.path.exists('/etc/fedora-release')
264 is_redhat = is_redhat or os.path.exists('/etc/redhat-release')
265
266 if is_redhat:
267 subprocess.check_output(["yum", "install", 'iozone3'])
268 return
269
270 try:
271 os_release_cont = open('/etc/os-release').read()
272
273 is_ubuntu = "Ubuntu" in os_release_cont
274
275 if is_ubuntu or "Debian GNU/Linux" in os_release_cont:
276 subprocess.check_output(["apt-get", "install", "iozone3"])
277 return
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200278 except (IOError, OSError):
koder aka kdanilov4af80852015-02-01 23:36:38 +0200279 pass
280
281 raise RuntimeError("Unknown host OS.")
282
283
284def install_iozone_static(iozone_url, dst):
285 if not os.path.isfile(dst):
286 import urllib
287 urllib.urlretrieve(iozone_url, dst)
288
289 st = os.stat(dst)
290 os.chmod(dst, st.st_mode | stat.S_IEXEC)
291
292
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200293def locate_iozone():
294 binary_path = which('iozone')
295
296 if binary_path is None:
297 binary_path = which('iozone3')
298
299 if binary_path is None:
300 sys.stderr.write("Can't found neither iozone not iozone3 binary"
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800301 "Provide --binary-path or --binary-url option")
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800302 return None
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200303
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800304 return binary_path
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200305
306# ------------------------------ FIO SUPPORT ---------------------------------
307
308
309def run_fio_once(benchmark, fio_path, tmpname, timeout=None):
koder aka kdanilov3f356262015-02-13 08:06:14 -0800310 if benchmark.size is None:
311 raise ValueError("You need to specify file size for fio")
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200312
313 cmd_line = [fio_path,
314 "--name=%s" % benchmark.action,
315 "--rw=%s" % benchmark.action,
316 "--blocksize=%sk" % benchmark.blocksize,
317 "--iodepth=%d" % benchmark.iodepth,
318 "--filename=%s" % tmpname,
319 "--size={0}k".format(benchmark.size),
320 "--numjobs={0}".format(benchmark.concurence),
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200321 "--runtime=60",
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200322 "--output-format=json",
323 "--sync=" + ('1' if benchmark.sync else '0')]
324
325 if timeout is not None:
326 cmd_line.append("--timeout=%d" % timeout)
327 cmd_line.append("--runtime=%d" % timeout)
328
329 if benchmark.direct_io:
330 cmd_line.append("--direct=1")
331
332 if benchmark.use_hight_io_priority:
333 cmd_line.append("--prio=0")
334
335 raw_out = subprocess.check_output(cmd_line)
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200336 return json.loads(raw_out)["jobs"][0], " ".join(cmd_line)
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200337
338
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800339def run_fio(benchmark, binary_path, all_files, timeout=None):
340 job_output, cmd_line = run_fio_once(benchmark, binary_path,
341 all_files[0], timeout)
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200342
343 if benchmark.action in ('write', 'randwrite'):
344 raw_result = job_output['write']
345 else:
346 raw_result = job_output['read']
347
348 res = {}
koder aka kdanilov78ba8952015-02-03 01:11:23 +0200349
350 # 'bw_dev bw_mean bw_max bw_min'.split()
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200351 for field in ["bw_mean", "iops"]:
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200352 res[field] = raw_result[field]
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200353 res["lat"] = raw_result["lat"]["mean"]
354 res["clat"] = raw_result["clat"]["mean"]
355 res["slat"] = raw_result["slat"]["mean"]
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200356
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200357 return res, cmd_line
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200358
359
360def locate_fio():
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800361 return which('fio')
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200362
363
364# ----------------------------------------------------------------------------
365
366
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800367def locate_binary(binary_tp, binary_path):
368 if binary_path is not None:
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200369 if os.path.isfile(binary_path):
370 if not os.access(binary_path, os.X_OK):
371 st = os.stat(binary_path)
372 os.chmod(binary_path, st.st_mode | stat.S_IEXEC)
373 else:
374 binary_path = None
375
376 if binary_path is not None:
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800377 return binary_path
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200378
379 if 'iozone' == binary_tp:
380 return locate_iozone()
381 else:
382 return locate_fio()
383
384
385def run_benchmark(binary_tp, *argv, **kwargs):
386 if 'iozone' == binary_tp:
387 return run_iozone(*argv, **kwargs)
388 else:
389 return run_fio(*argv, **kwargs)
390
391
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800392def prepare_benchmark(binary_tp, *argv, **kwargs):
393 if 'iozone' == binary_tp:
394 return {'all_files': prepare_iozone(*argv, **kwargs)}
395 else:
396 return {}
397
398
koder aka kdanilov4af80852015-02-01 23:36:38 +0200399def type_size(string):
400 try:
401 return re.match("\d+[KGBM]?", string, re.I).group(0)
402 except:
403 msg = "{0!r} don't looks like size-description string".format(string)
404 raise ValueError(msg)
405
406
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200407def type_size_ext(string):
408 if string.startswith("x"):
409 int(string[1:])
410 return string
411
412 if string.startswith("r"):
413 int(string[1:])
414 return string
415
416 try:
417 return re.match("\d+[KGBM]?", string, re.I).group(0)
418 except:
419 msg = "{0!r} don't looks like size-description string".format(string)
420 raise ValueError(msg)
421
422
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200423def ssize_to_kb(ssize):
424 try:
425 smap = dict(k=1, K=1, M=1024, m=1024, G=1024**2, g=1024**2)
426 for ext, coef in smap.items():
427 if ssize.endswith(ext):
428 return int(ssize[:-1]) * coef
429
430 if int(ssize) % 1024 != 0:
431 raise ValueError()
432
433 return int(ssize) / 1024
434
435 except (ValueError, TypeError, AttributeError):
436 tmpl = "Unknow size format {0!r} (or size not multiples 1024)"
437 raise ValueError(tmpl.format(ssize))
438
439
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200440def get_ram_size():
441 try:
442 with open("/proc/meminfo") as fd:
443 for ln in fd:
444 if "MemTotal:" in ln:
445 sz, kb = ln.split(':')[1].strip().split(" ")
446 assert kb == 'kB'
447 return int(sz)
448 except (ValueError, TypeError, AssertionError):
449 raise
450 # return None
451
452
koder aka kdanilov4af80852015-02-01 23:36:38 +0200453def parse_args(argv):
454 parser = argparse.ArgumentParser(
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200455 description="Run 'iozone' or 'fio' and return result")
456 parser.add_argument(
457 "--type", metavar="BINARY_TYPE",
458 choices=['iozone', 'fio'], required=True)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200459 parser.add_argument(
460 "--iodepth", metavar="IODEPTH", type=int,
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800461 help="I/O requests queue depths", required=True)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200462 parser.add_argument(
463 '-a', "--action", metavar="ACTION", type=str,
464 help="actions to run", required=True,
465 choices=["read", "write", "randread", "randwrite"])
466 parser.add_argument(
467 "--blocksize", metavar="BLOCKSIZE", type=type_size,
468 help="single operation block size", required=True)
469 parser.add_argument(
470 "--timeout", metavar="TIMEOUT", type=int,
471 help="runtime of a single run", default=None)
472 parser.add_argument(
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200473 "--iosize", metavar="SIZE", type=type_size_ext,
koder aka kdanilov4af80852015-02-01 23:36:38 +0200474 help="file size", default=None)
475 parser.add_argument(
476 "-s", "--sync", default=False, action="store_true",
477 help="exec sync after each write")
478 parser.add_argument(
479 "-d", "--direct-io", default=False, action="store_true",
480 help="use O_DIRECT", dest='directio')
481 parser.add_argument(
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800482 "-t", "--sync-time", default=None, type=int, metavar="UTC_TIME",
koder aka kdanilov4af80852015-02-01 23:36:38 +0200483 help="sleep till sime utc time", dest='sync_time')
484 parser.add_argument(
koder aka kdanilov4af80852015-02-01 23:36:38 +0200485 "--test-file", help="file path to run test on",
486 default=None, dest='test_file')
487 parser.add_argument(
koder aka kdanilov4ec0f712015-02-19 19:19:27 -0800488 "--binary-path", help="path to binary, used for testing",
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200489 default=None, dest='binary_path')
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800490 parser.add_argument(
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800491 "--prepare-only", default=False, action="store_true")
koder aka kdanilov3f356262015-02-13 08:06:14 -0800492 parser.add_argument("--concurrency", default=1, type=int)
koder aka kdanilove21d7472015-02-14 19:02:04 -0800493
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800494 parser.add_argument("--preparation-results", default="{}")
495
koder aka kdanilov4af80852015-02-01 23:36:38 +0200496 return parser.parse_args(argv)
497
498
koder aka kdanilove21d7472015-02-14 19:02:04 -0800499def sensor_thread(sensor_list, cmd_q, data_q):
500 while True:
501 try:
502 cmd_q.get(timeout=0.5)
503 data_q.put([])
504 return
505 except Queue.Empty:
506 pass
507
508
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800509def clean_prep(preparation_results):
510 if 'all_files' in preparation_results:
511 for fname in preparation_results['all_files']:
512 if os.path.isfile(fname):
513 os.unlink(fname)
514
515
koder aka kdanilov4af80852015-02-01 23:36:38 +0200516def main(argv):
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800517 if argv[0] == '--clean':
518 clean_prep(json.loads(argv[1]))
519 return 0
520
koder aka kdanilov4af80852015-02-01 23:36:38 +0200521 argv_obj = parse_args(argv)
522 argv_obj.blocksize = ssize_to_kb(argv_obj.blocksize)
523
524 if argv_obj.iosize is not None:
koder aka kdanilov4a72f122015-02-09 12:25:54 +0200525 if argv_obj.iosize.startswith('x'):
526 argv_obj.iosize = argv_obj.blocksize * int(argv_obj.iosize[1:])
527 elif argv_obj.iosize.startswith('r'):
528 rs = get_ram_size()
529 if rs is None:
530 sys.stderr.write("Can't determine ram size\n")
531 exit(1)
532 argv_obj.iosize = rs * int(argv_obj.iosize[1:])
533 else:
534 argv_obj.iosize = ssize_to_kb(argv_obj.iosize)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200535
koder aka kdanilov3f356262015-02-13 08:06:14 -0800536 benchmark = BenchmarkOption(argv_obj.concurrency,
koder aka kdanilov4af80852015-02-01 23:36:38 +0200537 argv_obj.iodepth,
538 argv_obj.action,
539 argv_obj.blocksize,
540 argv_obj.iosize)
541
542 benchmark.direct_io = argv_obj.directio
543
koder aka kdanilov98615bf2015-02-02 00:59:07 +0200544 if argv_obj.sync:
545 benchmark.sync = True
546
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800547 if argv_obj.prepare_only:
548 test_file_name = argv_obj.test_file
549 if test_file_name is None:
550 with warnings.catch_warnings():
551 warnings.simplefilter("ignore")
552 test_file_name = os.tmpnam()
koder aka kdanilov4af80852015-02-01 23:36:38 +0200553
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800554 fnames = prepare_benchmark(argv_obj.type,
555 benchmark,
556 test_file_name)
557 print json.dumps(fnames)
558 else:
559 preparation_results = json.loads(argv_obj.preparation_results)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200560
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800561 if not isinstance(preparation_results, dict):
562 raise ValueError("preparation_results should be a dict" +
563 " with all-string keys")
koder aka kdanilov4af80852015-02-01 23:36:38 +0200564
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800565 for key in preparation_results:
566 if not isinstance(key, basestring):
567 raise ValueError("preparation_results should be a dict" +
568 " with all-string keys")
koder aka kdanilov4af80852015-02-01 23:36:38 +0200569
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800570 if argv_obj.test_file and 'all_files' in preparation_results:
571 raise ValueError("Either --test-file or --preparation-results" +
572 " options should be provided, not both")
koder aka kdanilove21d7472015-02-14 19:02:04 -0800573
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800574 if argv_obj.test_file is not None:
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200575 preparation_results['all_files'] = [argv_obj.test_file]
koder aka kdanilov3f356262015-02-13 08:06:14 -0800576
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800577 autoremove = False
578 if 'all_files' not in preparation_results:
579 with warnings.catch_warnings():
580 warnings.simplefilter("ignore")
581 preparation_results['all_files'] = [os.tmpnam()]
582 autoremove = True
583
584 binary_path = locate_binary(argv_obj.type,
585 argv_obj.binary_path)
586
587 if binary_path is None:
588 sys.stderr.write("Can't locate binary {0}\n".format(argv_obj.type))
589 return 1
590
591 try:
592 if argv_obj.sync_time is not None:
593 dt = argv_obj.sync_time - time.time()
594 if dt > 0:
595 time.sleep(dt)
596
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800597 res, cmd = run_benchmark(argv_obj.type,
598 benchmark=benchmark,
599 binary_path=binary_path,
600 timeout=argv_obj.timeout,
601 **preparation_results)
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800602
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800603 res['__meta__'] = benchmark.__dict__.copy()
604 res['__meta__']['cmdline'] = cmd
605
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200606 import pprint
607 sys.stdout.write(pprint.pformat(res))
koder aka kdanilove21d7472015-02-14 19:02:04 -0800608
koder aka kdanilov8ad6e812015-03-22 14:42:18 +0200609 # sys.stdout.write(json.dumps(res))
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800610 if not argv_obj.prepare_only:
611 sys.stdout.write("\n")
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800612
koder aka kdanilov6e2ae792015-03-04 18:02:24 -0800613 finally:
614 if autoremove:
615 clean_prep(preparation_results)
koder aka kdanilov4af80852015-02-01 23:36:38 +0200616
617
koder aka kdanilov4af80852015-02-01 23:36:38 +0200618if __name__ == '__main__':
koder aka kdanilov4643fd62015-02-10 16:20:13 -0800619 exit(main(sys.argv[1:]))