#!/usr/bin/env python3 # # Process img-bench test templates # # Copyright (c) 2021 Virtuozzo International GmbH. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import sys import subprocess import re import json import simplebench from results_to_text import results_to_text from table_templater import Templater def bench_func(env, case): test = templater.gen(env['data'], case['data']) p = subprocess.run(test, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) if p.returncode == 0: try: m = re.search(r'Run completed in (\d+.\d+) seconds.', p.stdout) return {'seconds': float(m.group(1))} except Exception: return {'error': f'failed to parse qemu-img output: {p.stdout}'} else: return {'error': f'qemu-img failed: {p.returncode}: {p.stdout}'} if __name__ == '__main__': if len(sys.argv) > 1: print(""" Usage: img_bench_templater.py < path/to/test-template.sh This script generates performance tests from a test template (example below), runs them, and displays the results in a table. The template is read from stdin. It must be written in bash and end with a `qemu-img bench` invocation (whose result is parsed to get the test instance’s result). Use the following syntax in the template to create the various different test instances: column templating: {var1|var2|...} - test will use different values in different columns. You may use several {} constructions in the test, in this case product of all choice-sets will be used. row templating: [var1|var2|...] - similar thing to define rows (test-cases) Test template example: Assume you want to compare two qemu-img binaries, called qemu-img-old and qemu-img-new in your build directory in two test-cases with 4K writes and 64K writes. The template may look like this: qemu_img=/path/to/qemu/build/qemu-img-{old|new} $qemu_img create -f qcow2 /ssd/x.qcow2 1G $qemu_img bench -c 100 -d 8 [-s 4K|-s 64K] -w -t none -n /ssd/x.qcow2 When passing this to stdin of img_bench_templater.py, the resulting comparison table will contain two columns (for two binaries) and two rows (for two test-cases). In addition to displaying the results, script also stores results in JSON format into results.json file in current directory. """) sys.exit() templater = Templater(sys.stdin.read()) envs = [{'id': ' / '.join(x), 'data': x} for x in templater.columns] cases = [{'id': ' / '.join(x), 'data': x} for x in templater.rows] result = simplebench.bench(bench_func, envs, cases, count=5, initial_run=False) print(results_to_text(result)) with open('results.json', 'w') as f: json.dump(result, f, indent=4)