From ef7903eae7ca70c58733599f02d739040abb2e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sun, 22 Mar 2015 03:22:31 +0100 Subject: Add a parallel runner for clar As we are mostly I/O bound, the CPU tends to sit idle. With this script, we can split the work among multiple clar processes automatically, cutting down the time it takes for a full test run. --- script/pclar.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100755 script/pclar.py diff --git a/script/pclar.py b/script/pclar.py new file mode 100755 index 000000000..173db42b5 --- /dev/null +++ b/script/pclar.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +from __future__ import print_function, unicode_literals + +"""Parallel runner for clar +""" + +import sys, time +from os import path +import subprocess + +def parse_suites(exe): + suites = subprocess.check_output([exe, '-l']) + return map(lambda s: s.split(' ')[1], # get the name from each line of output + filter(lambda s: s, # Remove any empty lines + map(lambda s: s.strip(), # remove leading whitespace + suites.split('\n')[3:]))) # skip first three which are info messages + +def start_process(exe, suites): + argv = [exe] + for suite in suites: + argv.append("-s{}".format(suite)) + + return subprocess.Popen(argv, stdout=subprocess.PIPE) + +if __name__ == '__main__': + from argparse import ArgumentParser + + parser = ArgumentParser(description="Parallel runner for clar") + parser.add_argument('clar', type=unicode, help="Clar runner") + parser.add_argument('-j', '--jobs', type=int, default=1, + help="Number of parallel clars to run") + args = parser.parse_args() + + if not args.jobs > 0: + print("fatal: umber of jobs must be positive", file=sys.stderr) + exit(1) + + if not path.isfile(args.clar): + print("fatal: clar runner not found", file=sys.stderr) + exit(1) + + suites = parse_suites(args.clar) + plural = "" if args.jobs == 1 else "es" + print("Loaded {} suites, using {} process{}".format(len(suites), args.jobs, plural)) + + # Split the suites into groups so we can give the list to the + # runners. The last one gets a few more in case the number of + # suites does not split evenly into the runners + indices = range(0, len(suites)+1, len(suites) / args.jobs) + indices[-1] = len(suites) + + procs = [] + for i in range(1, len(indices)): + lower = indices[i-1] + upper = indices[i] + + procs.append(start_process(args.clar, suites[lower:upper])) + + # Processes have been started + print("Started processes: {}".format(map(lambda p: p.pid, procs))) + + while True: + running = len(filter(lambda p: p.poll() is None, procs)) + if running == 0: + break + + sys.stdout.write("\r{}Running {}".format("\033[K", running)) + sys.stdout.flush() + time.sleep(1) + + failures = len(filter(lambda p: p.poll() < 0, procs)) + errors = sum(filter(lambda p: p.poll() > 0, procs)) + successes = filter(lambda p: p.poll() == 0, procs) + + print("") + print("errors: {}, failures: {}".format(errors, failures)) -- cgit v1.2.1