File indexing completed on 2026-09-23 09:34:10
0001
0002
0003 """
0004 Combine the json files from the individual benchmark tests into
0005 a final master json file combining all benchmarks.
0006
0007 Benchmark results are expected to be all json files in the results
0008 directory.
0009 """
0010
0011
0012 MASTER_FILE=r'benchmarks/benchmarks.json'
0013
0014
0015 RESULTS_PATH=r'results'
0016
0017
0018 OUTPUT_FILE=r'results/summary.json'
0019
0020 import argparse
0021 import json
0022 from pathlib import Path
0023
0024
0025 class Error(Exception):
0026 '''Base class for exceptions in this module.'''
0027 pass
0028 class FileNotFoundError(Error):
0029 '''File does not exist.
0030
0031 Attributes:
0032 file: the file name
0033 message: error message
0034 '''
0035 def __init__(self, file):
0036 self.file = file
0037 self.message = 'No such file or directory: {}'.format(file)
0038
0039 class InvalidDefinitionError(Error):
0040 '''Raised for missing keys in the definitions.
0041
0042 Attributes:
0043 key: the missing key
0044 file: the definition file
0045 message: error message
0046 '''
0047 def __init__(self, key, file):
0048 self.key = key
0049 self.file = file
0050 self.message = "key '{}' not found in '{}'".format(key, file)
0051
0052 class InvalidResultError(Error):
0053 '''Raised for invalid benchmark result value.
0054
0055 Attributes:
0056 key: the missing key
0057 value: the invalid value
0058 file: the benchmark definition file
0059 message: error message
0060 '''
0061 def __init__(self, key, value, file):
0062 self.key = key
0063 self.value = value
0064 self.file = file
0065 self.message = "value '{}' for key '{}' invalid in benchmark file '{}'".format(
0066 value, key, file)
0067
0068 def collect_benchmarks():
0069 '''Collect all benchmark results and write results to a single file.'''
0070 print("Collecting all benchmark results")
0071
0072
0073 results = _load_master()
0074
0075
0076 results['benchmarks'] = _load_benchmarks()
0077
0078
0079 results = _aggregate_results(results)
0080
0081
0082 _save(results)
0083
0084
0085 for bm in results['benchmarks']:
0086 _print_benchmark(bm)
0087 _print_summary(results)
0088
0089 def _load_master():
0090 '''Load master definition.'''
0091 master_file = Path(MASTER_FILE)
0092 if not master_file.exists():
0093 raise FileNotFoundError(master_file)
0094 print(' --> Loading master definition from:', master_file)
0095 results = None
0096 with master_file.open() as f:
0097 results = json.load(f)
0098
0099 for key in ('name', 'title', 'description'):
0100 if not key in results:
0101 raise InvalidDefinitionError('target', master_file)
0102 return results
0103
0104 def _load_benchmarks():
0105 '''Load all benchmark results from the results folder.'''
0106 print(' --> Collecting all benchmarks')
0107 rootdir = Path(RESULTS_PATH)
0108 results = []
0109 for file in rootdir.glob('*.json'):
0110 print(' --> Loading file:', file, '... ', end='')
0111 with open(file) as f:
0112 bm = json.load(f)
0113
0114 if not 'tests' in bm:
0115 print('skipped (does not contain benchmark results).')
0116 continue
0117
0118
0119 for key in ('name', 'title', 'description', 'target', 'n_tests',
0120 'n_pass', 'n_fail', 'n_error', 'maximum', 'sum', 'value',
0121 'result'):
0122 if not key in bm:
0123 raise InvalidDefinitionError(key, file)
0124 if bm['result'] not in ('pass', 'fail', 'error'):
0125 raise InvalidResultError('result', bm['result'], file)
0126
0127 results.append(bm)
0128 print('done')
0129 return results
0130
0131 def _aggregate_results(results):
0132 '''Aggregate benchmark results.'''
0133 print(' --> Aggregating benchmark statistics')
0134 results['n_benchmarks'] = len(results['benchmarks'])
0135 results['n_pass'] = len([1 for t in results['benchmarks'] if t['result'] == 'pass'])
0136 results['n_fail'] = len([1 for t in results['benchmarks'] if t['result'] == 'fail'])
0137 results['n_error'] = len([1 for t in results['benchmarks'] if t['result'] == 'error'])
0138 if results['n_error'] > 0:
0139 results['result'] = 'error'
0140 elif results['n_fail'] == 0:
0141 results['result'] = 'pass'
0142 else:
0143 results['result'] = 'fail'
0144 return results
0145
0146 def _save(results):
0147 '''Save aggregated benchmark results'''
0148 ofile = Path(OUTPUT_FILE)
0149 print(' --> Saving results to:', ofile)
0150 with ofile.open('w') as f:
0151 json.dump(results, f, indent=4)
0152
0153 def _print_benchmark(bm):
0154 '''Print benchmark summary to the terminal.'''
0155 print('====================================================================')
0156 print(' Summary for:', bm['title'])
0157 print(' Pass: {}, Fail: {}, Error: {} out of {} total tests'.format(
0158 bm['n_pass'], bm['n_fail'], bm['n_error'],
0159 bm['n_tests']))
0160 print(' Weighted sum: {} / {}'.format(bm['sum'], bm['maximum']))
0161 print(' kBenchmark value: {} (target: {})'.format(
0162 bm['value'], bm['target']))
0163 print(' ===> status:', bm['result'])
0164
0165 def _print_summary(results):
0166 '''Print master benchmark summary to the terminal.'''
0167 print('====================================================================')
0168 print('MASTER BENCHMARK SUMMARY FOR:', results['title'].upper())
0169 print('Pass: {}, Fail: {}, Error: {} out of {} total benchmarks'.format(
0170 results['n_pass'], results['n_fail'], results['n_error'],
0171 results['n_benchmarks']))
0172 print('===> status:', results['result'])
0173 print('====================================================================')
0174
0175
0176 if __name__ == "__main__":
0177 try:
0178 collect_benchmarks()
0179 except Error as e:
0180 print()
0181 print('ERROR', e.message)