Merge pull request #152 from antmicro/jboc/benchmark
Benchmarks: add timeout parameter
This commit is contained in:
commit
4f9d6e413f
|
@ -63,7 +63,7 @@ jobs:
|
||||||
|
|
||||||
- stage: Benchmarks
|
- stage: Benchmarks
|
||||||
script:
|
script:
|
||||||
- python3 -m test.run_benchmarks test/benchmarks.yml --results-cache cache.json --html --heartbeat 60
|
- python3 -m test.run_benchmarks test/benchmarks.yml --results-cache cache.json --html --heartbeat 60 --timeout 540
|
||||||
# move benchmark artifacts to gh-pages/ directory that will be pushed to gh-pages branch
|
# move benchmark artifacts to gh-pages/ directory that will be pushed to gh-pages branch
|
||||||
- mkdir -p gh-pages
|
- mkdir -p gh-pages
|
||||||
- mv html/summary.html gh-pages/index.html
|
- mv html/summary.html gh-pages/index.html
|
||||||
|
|
|
@ -480,32 +480,34 @@ class RunCache(list):
|
||||||
return loaded
|
return loaded
|
||||||
|
|
||||||
|
|
||||||
def run_python(script, args):
|
def run_python(script, args, **kwargs):
|
||||||
command = ['python3', script, *args]
|
command = ['python3', script, *args]
|
||||||
proc = subprocess.run(command, stdout=subprocess.PIPE, cwd=os.path.dirname(script))
|
proc = subprocess.run(command, stdout=subprocess.PIPE, cwd=os.path.dirname(script), **kwargs)
|
||||||
return str(proc.stdout)
|
return str(proc.stdout)
|
||||||
|
|
||||||
|
|
||||||
def run_single_benchmark(func_args):
|
BenchmarkArgs = namedtuple('BenchmarkArgs', ['config', 'output_dir', 'ignore_failures', 'timeout'])
|
||||||
config, output_dir, ignore_failures = func_args
|
|
||||||
|
|
||||||
|
def run_single_benchmark(fargs):
|
||||||
# run as separate process, because else we cannot capture all output from verilator
|
# run as separate process, because else we cannot capture all output from verilator
|
||||||
print(' {}: {}'.format(config.name, ' '.join(config.as_args())))
|
print(' {}: {}'.format(fargs.config.name, ' '.join(fargs.config.as_args())))
|
||||||
try:
|
try:
|
||||||
args = config.as_args() + ['--output-dir', output_dir, '--log-level', 'warning']
|
args = fargs.config.as_args() + ['--output-dir', fargs.output_dir, '--log-level', 'warning']
|
||||||
output = run_python(benchmark.__file__, args)
|
output = run_python(benchmark.__file__, args, timeout=fargs.timeout)
|
||||||
result = BenchmarkResult(output)
|
result = BenchmarkResult(output)
|
||||||
# exit if checker had any read error
|
# exit if checker had any read error
|
||||||
if result.checker_errors != 0:
|
if result.checker_errors != 0:
|
||||||
raise RuntimeError('Error during benchmark: checker_errors = {}, args = {}'.format(
|
raise RuntimeError('Error during benchmark: checker_errors = {}, args = {}'.format(
|
||||||
result.checker_errors, config.as_args()
|
result.checker_errors, fargs.config.as_args()
|
||||||
))
|
))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if ignore_failures:
|
if fargs.ignore_failures:
|
||||||
print(' {}: ERROR: {}'.format(config.name, e))
|
print(' {}: ERROR: {}'.format(fargs.config.name, e))
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
print(' {}: ok'.format(config.name))
|
print(' {}: ok'.format(fargs.config.name))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -513,7 +515,7 @@ InQueueItem = namedtuple('InQueueItem', ['index', 'config'])
|
||||||
OutQueueItem = namedtuple('OutQueueItem', ['index', 'result'])
|
OutQueueItem = namedtuple('OutQueueItem', ['index', 'result'])
|
||||||
|
|
||||||
|
|
||||||
def run_parallel(configurations, output_base_dir, njobs, ignore_failures):
|
def run_parallel(configurations, output_base_dir, njobs, ignore_failures, timeout):
|
||||||
from multiprocessing import Process, Queue
|
from multiprocessing import Process, Queue
|
||||||
import queue
|
import queue
|
||||||
|
|
||||||
|
@ -522,7 +524,8 @@ def run_parallel(configurations, output_base_dir, njobs, ignore_failures):
|
||||||
in_item = in_queue.get()
|
in_item = in_queue.get()
|
||||||
if in_item is None:
|
if in_item is None:
|
||||||
return
|
return
|
||||||
result = run_single_benchmark((in_item.config, out_dir, ignore_failures))
|
fargs = BenchmarkArgs(in_item.config, out_dir, ignore_failures, timeout)
|
||||||
|
result = run_single_benchmark(fargs)
|
||||||
out_queue.put(OutQueueItem(in_item.index, result))
|
out_queue.put(OutQueueItem(in_item.index, result))
|
||||||
|
|
||||||
if njobs == 0:
|
if njobs == 0:
|
||||||
|
@ -556,12 +559,13 @@ def run_parallel(configurations, output_base_dir, njobs, ignore_failures):
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def run_benchmarks(configurations, output_base_dir, njobs, ignore_failures):
|
def run_benchmarks(configurations, output_base_dir, njobs, ignore_failures, timeout):
|
||||||
print('Running {:d} benchmarks ...'.format(len(configurations)))
|
print('Running {:d} benchmarks ...'.format(len(configurations)))
|
||||||
if njobs == 1:
|
if njobs == 1:
|
||||||
results = [run_single_benchmark((config, output_base_dir, ignore_failures)) for config in configurations]
|
results = [run_single_benchmark(BenchmarkArgs(config, output_base_dir, ignore_failures, timeout))
|
||||||
|
for config in configurations]
|
||||||
else:
|
else:
|
||||||
results = run_parallel(configurations, output_base_dir, njobs, ignore_failures)
|
results = run_parallel(configurations, output_base_dir, njobs, ignore_failures, timeout)
|
||||||
run_data = [RunCache.RunData(config, result) for config, result in zip(configurations, results)]
|
run_data = [RunCache.RunData(config, result) for config, result in zip(configurations, results)]
|
||||||
return run_data
|
return run_data
|
||||||
|
|
||||||
|
@ -585,6 +589,7 @@ def main(argv=None):
|
||||||
parser.add_argument('--output-dir', default='build', help='Directory to store benchmark build output')
|
parser.add_argument('--output-dir', default='build', help='Directory to store benchmark build output')
|
||||||
parser.add_argument('--njobs', default=0, type=int, help='Use N parallel jobs to run benchmarks (default=0, which uses CPU count)')
|
parser.add_argument('--njobs', default=0, type=int, help='Use N parallel jobs to run benchmarks (default=0, which uses CPU count)')
|
||||||
parser.add_argument('--heartbeat', default=0, type=int, help='Print heartbeat message with given interval (default=0 => never)')
|
parser.add_argument('--heartbeat', default=0, type=int, help='Print heartbeat message with given interval (default=0 => never)')
|
||||||
|
parser.add_argument('--timeout', default=None, help='Set timeout for a single benchmark')
|
||||||
parser.add_argument('--results-cache', help="""Use given JSON file as results cache. If the file exists,
|
parser.add_argument('--results-cache', help="""Use given JSON file as results cache. If the file exists,
|
||||||
it will be loaded instead of running actual benchmarks,
|
it will be loaded instead of running actual benchmarks,
|
||||||
else benchmarks will be run normally, and then saved
|
else benchmarks will be run normally, and then saved
|
||||||
|
@ -621,7 +626,9 @@ def main(argv=None):
|
||||||
if args.heartbeat:
|
if args.heartbeat:
|
||||||
heartbeat_cmd = ['/bin/sh', '-c', 'while true; do sleep %d; echo Heartbeat...; done' % args.heartbeat]
|
heartbeat_cmd = ['/bin/sh', '-c', 'while true; do sleep %d; echo Heartbeat...; done' % args.heartbeat]
|
||||||
heartbeat = subprocess.Popen(heartbeat_cmd)
|
heartbeat = subprocess.Popen(heartbeat_cmd)
|
||||||
run_data = run_benchmarks(configurations, args.output_dir, args.njobs, not args.fail_fast)
|
if args.timeout is not None:
|
||||||
|
args.timeout = int(args.timeout)
|
||||||
|
run_data = run_benchmarks(configurations, args.output_dir, args.njobs, not args.fail_fast, args.timeout)
|
||||||
if args.heartbeat:
|
if args.heartbeat:
|
||||||
heartbeat.kill()
|
heartbeat.kill()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue