1a8c51b3fSopenharmony_ci"""report.py - Utilities for reporting statistics about benchmark results 2a8c51b3fSopenharmony_ci""" 3a8c51b3fSopenharmony_ci 4a8c51b3fSopenharmony_ciimport unittest 5a8c51b3fSopenharmony_ciimport os 6a8c51b3fSopenharmony_ciimport re 7a8c51b3fSopenharmony_ciimport copy 8a8c51b3fSopenharmony_ciimport random 9a8c51b3fSopenharmony_ci 10a8c51b3fSopenharmony_cifrom scipy.stats import mannwhitneyu, gmean 11a8c51b3fSopenharmony_cifrom numpy import array 12a8c51b3fSopenharmony_ci 13a8c51b3fSopenharmony_ci 14a8c51b3fSopenharmony_ciclass BenchmarkColor(object): 15a8c51b3fSopenharmony_ci def __init__(self, name, code): 16a8c51b3fSopenharmony_ci self.name = name 17a8c51b3fSopenharmony_ci self.code = code 18a8c51b3fSopenharmony_ci 19a8c51b3fSopenharmony_ci def __repr__(self): 20a8c51b3fSopenharmony_ci return '%s%r' % (self.__class__.__name__, 21a8c51b3fSopenharmony_ci (self.name, self.code)) 22a8c51b3fSopenharmony_ci 23a8c51b3fSopenharmony_ci def __format__(self, format): 24a8c51b3fSopenharmony_ci return self.code 25a8c51b3fSopenharmony_ci 26a8c51b3fSopenharmony_ci 27a8c51b3fSopenharmony_ci# Benchmark Colors Enumeration 28a8c51b3fSopenharmony_ciBC_NONE = BenchmarkColor('NONE', '') 29a8c51b3fSopenharmony_ciBC_MAGENTA = BenchmarkColor('MAGENTA', '\033[95m') 30a8c51b3fSopenharmony_ciBC_CYAN = BenchmarkColor('CYAN', '\033[96m') 31a8c51b3fSopenharmony_ciBC_OKBLUE = BenchmarkColor('OKBLUE', '\033[94m') 32a8c51b3fSopenharmony_ciBC_OKGREEN = BenchmarkColor('OKGREEN', '\033[32m') 33a8c51b3fSopenharmony_ciBC_HEADER = BenchmarkColor('HEADER', '\033[92m') 34a8c51b3fSopenharmony_ciBC_WARNING = BenchmarkColor('WARNING', '\033[93m') 35a8c51b3fSopenharmony_ciBC_WHITE = BenchmarkColor('WHITE', '\033[97m') 36a8c51b3fSopenharmony_ciBC_FAIL = BenchmarkColor('FAIL', '\033[91m') 37a8c51b3fSopenharmony_ciBC_ENDC = BenchmarkColor('ENDC', '\033[0m') 38a8c51b3fSopenharmony_ciBC_BOLD = BenchmarkColor('BOLD', '\033[1m') 39a8c51b3fSopenharmony_ciBC_UNDERLINE = BenchmarkColor('UNDERLINE', '\033[4m') 40a8c51b3fSopenharmony_ci 41a8c51b3fSopenharmony_ciUTEST_MIN_REPETITIONS = 2 42a8c51b3fSopenharmony_ciUTEST_OPTIMAL_REPETITIONS = 9 # Lowest reasonable number, More is better. 43a8c51b3fSopenharmony_ciUTEST_COL_NAME = "_pvalue" 44a8c51b3fSopenharmony_ci 45a8c51b3fSopenharmony_ci_TIME_UNIT_TO_SECONDS_MULTIPLIER = { 46a8c51b3fSopenharmony_ci "s": 1.0, 47a8c51b3fSopenharmony_ci "ms": 1e-3, 48a8c51b3fSopenharmony_ci "us": 1e-6, 49a8c51b3fSopenharmony_ci "ns": 1e-9, 50a8c51b3fSopenharmony_ci} 51a8c51b3fSopenharmony_ci 52a8c51b3fSopenharmony_ci 53a8c51b3fSopenharmony_cidef color_format(use_color, fmt_str, *args, **kwargs): 54a8c51b3fSopenharmony_ci """ 55a8c51b3fSopenharmony_ci Return the result of 'fmt_str.format(*args, **kwargs)' after transforming 56a8c51b3fSopenharmony_ci 'args' and 'kwargs' according to the value of 'use_color'. If 'use_color' 57a8c51b3fSopenharmony_ci is False then all color codes in 'args' and 'kwargs' are replaced with 58a8c51b3fSopenharmony_ci the empty string. 59a8c51b3fSopenharmony_ci """ 60a8c51b3fSopenharmony_ci assert use_color is True or use_color is False 61a8c51b3fSopenharmony_ci if not use_color: 62a8c51b3fSopenharmony_ci args = [arg if not isinstance(arg, BenchmarkColor) else BC_NONE 63a8c51b3fSopenharmony_ci for arg in args] 64a8c51b3fSopenharmony_ci kwargs = {key: arg if not isinstance(arg, BenchmarkColor) else BC_NONE 65a8c51b3fSopenharmony_ci for key, arg in kwargs.items()} 66a8c51b3fSopenharmony_ci return fmt_str.format(*args, **kwargs) 67a8c51b3fSopenharmony_ci 68a8c51b3fSopenharmony_ci 69a8c51b3fSopenharmony_cidef find_longest_name(benchmark_list): 70a8c51b3fSopenharmony_ci """ 71a8c51b3fSopenharmony_ci Return the length of the longest benchmark name in a given list of 72a8c51b3fSopenharmony_ci benchmark JSON objects 73a8c51b3fSopenharmony_ci """ 74a8c51b3fSopenharmony_ci longest_name = 1 75a8c51b3fSopenharmony_ci for bc in benchmark_list: 76a8c51b3fSopenharmony_ci if len(bc['name']) > longest_name: 77a8c51b3fSopenharmony_ci longest_name = len(bc['name']) 78a8c51b3fSopenharmony_ci return longest_name 79a8c51b3fSopenharmony_ci 80a8c51b3fSopenharmony_ci 81a8c51b3fSopenharmony_cidef calculate_change(old_val, new_val): 82a8c51b3fSopenharmony_ci """ 83a8c51b3fSopenharmony_ci Return a float representing the decimal change between old_val and new_val. 84a8c51b3fSopenharmony_ci """ 85a8c51b3fSopenharmony_ci if old_val == 0 and new_val == 0: 86a8c51b3fSopenharmony_ci return 0.0 87a8c51b3fSopenharmony_ci if old_val == 0: 88a8c51b3fSopenharmony_ci return float(new_val - old_val) / (float(old_val + new_val) / 2) 89a8c51b3fSopenharmony_ci return float(new_val - old_val) / abs(old_val) 90a8c51b3fSopenharmony_ci 91a8c51b3fSopenharmony_ci 92a8c51b3fSopenharmony_cidef filter_benchmark(json_orig, family, replacement=""): 93a8c51b3fSopenharmony_ci """ 94a8c51b3fSopenharmony_ci Apply a filter to the json, and only leave the 'family' of benchmarks. 95a8c51b3fSopenharmony_ci """ 96a8c51b3fSopenharmony_ci regex = re.compile(family) 97a8c51b3fSopenharmony_ci filtered = {} 98a8c51b3fSopenharmony_ci filtered['benchmarks'] = [] 99a8c51b3fSopenharmony_ci for be in json_orig['benchmarks']: 100a8c51b3fSopenharmony_ci if not regex.search(be['name']): 101a8c51b3fSopenharmony_ci continue 102a8c51b3fSopenharmony_ci filteredbench = copy.deepcopy(be) # Do NOT modify the old name! 103a8c51b3fSopenharmony_ci filteredbench['name'] = regex.sub(replacement, filteredbench['name']) 104a8c51b3fSopenharmony_ci filtered['benchmarks'].append(filteredbench) 105a8c51b3fSopenharmony_ci return filtered 106a8c51b3fSopenharmony_ci 107a8c51b3fSopenharmony_ci 108a8c51b3fSopenharmony_cidef get_unique_benchmark_names(json): 109a8c51b3fSopenharmony_ci """ 110a8c51b3fSopenharmony_ci While *keeping* the order, give all the unique 'names' used for benchmarks. 111a8c51b3fSopenharmony_ci """ 112a8c51b3fSopenharmony_ci seen = set() 113a8c51b3fSopenharmony_ci uniqued = [x['name'] for x in json['benchmarks'] 114a8c51b3fSopenharmony_ci if x['name'] not in seen and 115a8c51b3fSopenharmony_ci (seen.add(x['name']) or True)] 116a8c51b3fSopenharmony_ci return uniqued 117a8c51b3fSopenharmony_ci 118a8c51b3fSopenharmony_ci 119a8c51b3fSopenharmony_cidef intersect(list1, list2): 120a8c51b3fSopenharmony_ci """ 121a8c51b3fSopenharmony_ci Given two lists, get a new list consisting of the elements only contained 122a8c51b3fSopenharmony_ci in *both of the input lists*, while preserving the ordering. 123a8c51b3fSopenharmony_ci """ 124a8c51b3fSopenharmony_ci return [x for x in list1 if x in list2] 125a8c51b3fSopenharmony_ci 126a8c51b3fSopenharmony_ci 127a8c51b3fSopenharmony_cidef is_potentially_comparable_benchmark(x): 128a8c51b3fSopenharmony_ci return ('time_unit' in x and 'real_time' in x and 'cpu_time' in x) 129a8c51b3fSopenharmony_ci 130a8c51b3fSopenharmony_ci 131a8c51b3fSopenharmony_cidef partition_benchmarks(json1, json2): 132a8c51b3fSopenharmony_ci """ 133a8c51b3fSopenharmony_ci While preserving the ordering, find benchmarks with the same names in 134a8c51b3fSopenharmony_ci both of the inputs, and group them. 135a8c51b3fSopenharmony_ci (i.e. partition/filter into groups with common name) 136a8c51b3fSopenharmony_ci """ 137a8c51b3fSopenharmony_ci json1_unique_names = get_unique_benchmark_names(json1) 138a8c51b3fSopenharmony_ci json2_unique_names = get_unique_benchmark_names(json2) 139a8c51b3fSopenharmony_ci names = intersect(json1_unique_names, json2_unique_names) 140a8c51b3fSopenharmony_ci partitions = [] 141a8c51b3fSopenharmony_ci for name in names: 142a8c51b3fSopenharmony_ci time_unit = None 143a8c51b3fSopenharmony_ci # Pick the time unit from the first entry of the lhs benchmark. 144a8c51b3fSopenharmony_ci # We should be careful not to crash with unexpected input. 145a8c51b3fSopenharmony_ci for x in json1['benchmarks']: 146a8c51b3fSopenharmony_ci if (x['name'] == name and is_potentially_comparable_benchmark(x)): 147a8c51b3fSopenharmony_ci time_unit = x['time_unit'] 148a8c51b3fSopenharmony_ci break 149a8c51b3fSopenharmony_ci if time_unit is None: 150a8c51b3fSopenharmony_ci continue 151a8c51b3fSopenharmony_ci # Filter by name and time unit. 152a8c51b3fSopenharmony_ci # All the repetitions are assumed to be comparable. 153a8c51b3fSopenharmony_ci lhs = [x for x in json1['benchmarks'] if x['name'] == name and 154a8c51b3fSopenharmony_ci x['time_unit'] == time_unit] 155a8c51b3fSopenharmony_ci rhs = [x for x in json2['benchmarks'] if x['name'] == name and 156a8c51b3fSopenharmony_ci x['time_unit'] == time_unit] 157a8c51b3fSopenharmony_ci partitions.append([lhs, rhs]) 158a8c51b3fSopenharmony_ci return partitions 159a8c51b3fSopenharmony_ci 160a8c51b3fSopenharmony_ci 161a8c51b3fSopenharmony_cidef get_timedelta_field_as_seconds(benchmark, field_name): 162a8c51b3fSopenharmony_ci """ 163a8c51b3fSopenharmony_ci Get value of field_name field of benchmark, which is time with time unit 164a8c51b3fSopenharmony_ci time_unit, as time in seconds. 165a8c51b3fSopenharmony_ci """ 166a8c51b3fSopenharmony_ci timedelta = benchmark[field_name] 167a8c51b3fSopenharmony_ci time_unit = benchmark.get('time_unit', 's') 168a8c51b3fSopenharmony_ci return timedelta * _TIME_UNIT_TO_SECONDS_MULTIPLIER.get(time_unit) 169a8c51b3fSopenharmony_ci 170a8c51b3fSopenharmony_ci 171a8c51b3fSopenharmony_cidef calculate_geomean(json): 172a8c51b3fSopenharmony_ci """ 173a8c51b3fSopenharmony_ci Extract all real/cpu times from all the benchmarks as seconds, 174a8c51b3fSopenharmony_ci and calculate their geomean. 175a8c51b3fSopenharmony_ci """ 176a8c51b3fSopenharmony_ci times = [] 177a8c51b3fSopenharmony_ci for benchmark in json['benchmarks']: 178a8c51b3fSopenharmony_ci if 'run_type' in benchmark and benchmark['run_type'] == 'aggregate': 179a8c51b3fSopenharmony_ci continue 180a8c51b3fSopenharmony_ci times.append([get_timedelta_field_as_seconds(benchmark, 'real_time'), 181a8c51b3fSopenharmony_ci get_timedelta_field_as_seconds(benchmark, 'cpu_time')]) 182a8c51b3fSopenharmony_ci return gmean(times) if times else array([]) 183a8c51b3fSopenharmony_ci 184a8c51b3fSopenharmony_ci 185a8c51b3fSopenharmony_cidef extract_field(partition, field_name): 186a8c51b3fSopenharmony_ci # The count of elements may be different. We want *all* of them. 187a8c51b3fSopenharmony_ci lhs = [x[field_name] for x in partition[0]] 188a8c51b3fSopenharmony_ci rhs = [x[field_name] for x in partition[1]] 189a8c51b3fSopenharmony_ci return [lhs, rhs] 190a8c51b3fSopenharmony_ci 191a8c51b3fSopenharmony_ci 192a8c51b3fSopenharmony_cidef calc_utest(timings_cpu, timings_time): 193a8c51b3fSopenharmony_ci min_rep_cnt = min(len(timings_time[0]), 194a8c51b3fSopenharmony_ci len(timings_time[1]), 195a8c51b3fSopenharmony_ci len(timings_cpu[0]), 196a8c51b3fSopenharmony_ci len(timings_cpu[1])) 197a8c51b3fSopenharmony_ci 198a8c51b3fSopenharmony_ci # Does *everything* has at least UTEST_MIN_REPETITIONS repetitions? 199a8c51b3fSopenharmony_ci if min_rep_cnt < UTEST_MIN_REPETITIONS: 200a8c51b3fSopenharmony_ci return False, None, None 201a8c51b3fSopenharmony_ci 202a8c51b3fSopenharmony_ci time_pvalue = mannwhitneyu( 203a8c51b3fSopenharmony_ci timings_time[0], timings_time[1], alternative='two-sided').pvalue 204a8c51b3fSopenharmony_ci cpu_pvalue = mannwhitneyu( 205a8c51b3fSopenharmony_ci timings_cpu[0], timings_cpu[1], alternative='two-sided').pvalue 206a8c51b3fSopenharmony_ci 207a8c51b3fSopenharmony_ci return (min_rep_cnt >= UTEST_OPTIMAL_REPETITIONS), cpu_pvalue, time_pvalue 208a8c51b3fSopenharmony_ci 209a8c51b3fSopenharmony_ci 210a8c51b3fSopenharmony_cidef print_utest(bc_name, utest, utest_alpha, first_col_width, use_color=True): 211a8c51b3fSopenharmony_ci def get_utest_color(pval): 212a8c51b3fSopenharmony_ci return BC_FAIL if pval >= utest_alpha else BC_OKGREEN 213a8c51b3fSopenharmony_ci 214a8c51b3fSopenharmony_ci # Check if we failed miserably with minimum required repetitions for utest 215a8c51b3fSopenharmony_ci if not utest['have_optimal_repetitions'] and utest['cpu_pvalue'] is None and utest['time_pvalue'] is None: 216a8c51b3fSopenharmony_ci return [] 217a8c51b3fSopenharmony_ci 218a8c51b3fSopenharmony_ci dsc = "U Test, Repetitions: {} vs {}".format( 219a8c51b3fSopenharmony_ci utest['nr_of_repetitions'], utest['nr_of_repetitions_other']) 220a8c51b3fSopenharmony_ci dsc_color = BC_OKGREEN 221a8c51b3fSopenharmony_ci 222a8c51b3fSopenharmony_ci # We still got some results to show but issue a warning about it. 223a8c51b3fSopenharmony_ci if not utest['have_optimal_repetitions']: 224a8c51b3fSopenharmony_ci dsc_color = BC_WARNING 225a8c51b3fSopenharmony_ci dsc += ". WARNING: Results unreliable! {}+ repetitions recommended.".format( 226a8c51b3fSopenharmony_ci UTEST_OPTIMAL_REPETITIONS) 227a8c51b3fSopenharmony_ci 228a8c51b3fSopenharmony_ci special_str = "{}{:<{}s}{endc}{}{:16.4f}{endc}{}{:16.4f}{endc}{} {}" 229a8c51b3fSopenharmony_ci 230a8c51b3fSopenharmony_ci return [color_format(use_color, 231a8c51b3fSopenharmony_ci special_str, 232a8c51b3fSopenharmony_ci BC_HEADER, 233a8c51b3fSopenharmony_ci "{}{}".format(bc_name, UTEST_COL_NAME), 234a8c51b3fSopenharmony_ci first_col_width, 235a8c51b3fSopenharmony_ci get_utest_color( 236a8c51b3fSopenharmony_ci utest['time_pvalue']), utest['time_pvalue'], 237a8c51b3fSopenharmony_ci get_utest_color( 238a8c51b3fSopenharmony_ci utest['cpu_pvalue']), utest['cpu_pvalue'], 239a8c51b3fSopenharmony_ci dsc_color, dsc, 240a8c51b3fSopenharmony_ci endc=BC_ENDC)] 241a8c51b3fSopenharmony_ci 242a8c51b3fSopenharmony_ci 243a8c51b3fSopenharmony_cidef get_difference_report( 244a8c51b3fSopenharmony_ci json1, 245a8c51b3fSopenharmony_ci json2, 246a8c51b3fSopenharmony_ci utest=False): 247a8c51b3fSopenharmony_ci """ 248a8c51b3fSopenharmony_ci Calculate and report the difference between each test of two benchmarks 249a8c51b3fSopenharmony_ci runs specified as 'json1' and 'json2'. Output is another json containing 250a8c51b3fSopenharmony_ci relevant details for each test run. 251a8c51b3fSopenharmony_ci """ 252a8c51b3fSopenharmony_ci assert utest is True or utest is False 253a8c51b3fSopenharmony_ci 254a8c51b3fSopenharmony_ci diff_report = [] 255a8c51b3fSopenharmony_ci partitions = partition_benchmarks(json1, json2) 256a8c51b3fSopenharmony_ci for partition in partitions: 257a8c51b3fSopenharmony_ci benchmark_name = partition[0][0]['name'] 258a8c51b3fSopenharmony_ci label = partition[0][0]['label'] if 'label' in partition[0][0] else '' 259a8c51b3fSopenharmony_ci time_unit = partition[0][0]['time_unit'] 260a8c51b3fSopenharmony_ci measurements = [] 261a8c51b3fSopenharmony_ci utest_results = {} 262a8c51b3fSopenharmony_ci # Careful, we may have different repetition count. 263a8c51b3fSopenharmony_ci for i in range(min(len(partition[0]), len(partition[1]))): 264a8c51b3fSopenharmony_ci bn = partition[0][i] 265a8c51b3fSopenharmony_ci other_bench = partition[1][i] 266a8c51b3fSopenharmony_ci measurements.append({ 267a8c51b3fSopenharmony_ci 'real_time': bn['real_time'], 268a8c51b3fSopenharmony_ci 'cpu_time': bn['cpu_time'], 269a8c51b3fSopenharmony_ci 'real_time_other': other_bench['real_time'], 270a8c51b3fSopenharmony_ci 'cpu_time_other': other_bench['cpu_time'], 271a8c51b3fSopenharmony_ci 'time': calculate_change(bn['real_time'], other_bench['real_time']), 272a8c51b3fSopenharmony_ci 'cpu': calculate_change(bn['cpu_time'], other_bench['cpu_time']) 273a8c51b3fSopenharmony_ci }) 274a8c51b3fSopenharmony_ci 275a8c51b3fSopenharmony_ci # After processing the whole partition, if requested, do the U test. 276a8c51b3fSopenharmony_ci if utest: 277a8c51b3fSopenharmony_ci timings_cpu = extract_field(partition, 'cpu_time') 278a8c51b3fSopenharmony_ci timings_time = extract_field(partition, 'real_time') 279a8c51b3fSopenharmony_ci have_optimal_repetitions, cpu_pvalue, time_pvalue = calc_utest( 280a8c51b3fSopenharmony_ci timings_cpu, timings_time) 281a8c51b3fSopenharmony_ci if cpu_pvalue and time_pvalue: 282a8c51b3fSopenharmony_ci utest_results = { 283a8c51b3fSopenharmony_ci 'have_optimal_repetitions': have_optimal_repetitions, 284a8c51b3fSopenharmony_ci 'cpu_pvalue': cpu_pvalue, 285a8c51b3fSopenharmony_ci 'time_pvalue': time_pvalue, 286a8c51b3fSopenharmony_ci 'nr_of_repetitions': len(timings_cpu[0]), 287a8c51b3fSopenharmony_ci 'nr_of_repetitions_other': len(timings_cpu[1]) 288a8c51b3fSopenharmony_ci } 289a8c51b3fSopenharmony_ci 290a8c51b3fSopenharmony_ci # Store only if we had any measurements for given benchmark. 291a8c51b3fSopenharmony_ci # E.g. partition_benchmarks will filter out the benchmarks having 292a8c51b3fSopenharmony_ci # time units which are not compatible with other time units in the 293a8c51b3fSopenharmony_ci # benchmark suite. 294a8c51b3fSopenharmony_ci if measurements: 295a8c51b3fSopenharmony_ci run_type = partition[0][0]['run_type'] if 'run_type' in partition[0][0] else '' 296a8c51b3fSopenharmony_ci aggregate_name = partition[0][0]['aggregate_name'] if run_type == 'aggregate' and 'aggregate_name' in partition[0][0] else '' 297a8c51b3fSopenharmony_ci diff_report.append({ 298a8c51b3fSopenharmony_ci 'name': benchmark_name, 299a8c51b3fSopenharmony_ci 'label': label, 300a8c51b3fSopenharmony_ci 'measurements': measurements, 301a8c51b3fSopenharmony_ci 'time_unit': time_unit, 302a8c51b3fSopenharmony_ci 'run_type': run_type, 303a8c51b3fSopenharmony_ci 'aggregate_name': aggregate_name, 304a8c51b3fSopenharmony_ci 'utest': utest_results 305a8c51b3fSopenharmony_ci }) 306a8c51b3fSopenharmony_ci 307a8c51b3fSopenharmony_ci lhs_gmean = calculate_geomean(json1) 308a8c51b3fSopenharmony_ci rhs_gmean = calculate_geomean(json2) 309a8c51b3fSopenharmony_ci if lhs_gmean.any() and rhs_gmean.any(): 310a8c51b3fSopenharmony_ci diff_report.append({ 311a8c51b3fSopenharmony_ci 'name': 'OVERALL_GEOMEAN', 312a8c51b3fSopenharmony_ci 'label': '', 313a8c51b3fSopenharmony_ci 'measurements': [{ 314a8c51b3fSopenharmony_ci 'real_time': lhs_gmean[0], 315a8c51b3fSopenharmony_ci 'cpu_time': lhs_gmean[1], 316a8c51b3fSopenharmony_ci 'real_time_other': rhs_gmean[0], 317a8c51b3fSopenharmony_ci 'cpu_time_other': rhs_gmean[1], 318a8c51b3fSopenharmony_ci 'time': calculate_change(lhs_gmean[0], rhs_gmean[0]), 319a8c51b3fSopenharmony_ci 'cpu': calculate_change(lhs_gmean[1], rhs_gmean[1]) 320a8c51b3fSopenharmony_ci }], 321a8c51b3fSopenharmony_ci 'time_unit': 's', 322a8c51b3fSopenharmony_ci 'run_type': 'aggregate', 323a8c51b3fSopenharmony_ci 'aggregate_name': 'geomean', 324a8c51b3fSopenharmony_ci 'utest': {} 325a8c51b3fSopenharmony_ci }) 326a8c51b3fSopenharmony_ci 327a8c51b3fSopenharmony_ci return diff_report 328a8c51b3fSopenharmony_ci 329a8c51b3fSopenharmony_ci 330a8c51b3fSopenharmony_cidef print_difference_report( 331a8c51b3fSopenharmony_ci json_diff_report, 332a8c51b3fSopenharmony_ci include_aggregates_only=False, 333a8c51b3fSopenharmony_ci utest=False, 334a8c51b3fSopenharmony_ci utest_alpha=0.05, 335a8c51b3fSopenharmony_ci use_color=True): 336a8c51b3fSopenharmony_ci """ 337a8c51b3fSopenharmony_ci Calculate and report the difference between each test of two benchmarks 338a8c51b3fSopenharmony_ci runs specified as 'json1' and 'json2'. 339a8c51b3fSopenharmony_ci """ 340a8c51b3fSopenharmony_ci assert utest is True or utest is False 341a8c51b3fSopenharmony_ci 342a8c51b3fSopenharmony_ci def get_color(res): 343a8c51b3fSopenharmony_ci if res > 0.05: 344a8c51b3fSopenharmony_ci return BC_FAIL 345a8c51b3fSopenharmony_ci elif res > -0.07: 346a8c51b3fSopenharmony_ci return BC_WHITE 347a8c51b3fSopenharmony_ci else: 348a8c51b3fSopenharmony_ci return BC_CYAN 349a8c51b3fSopenharmony_ci 350a8c51b3fSopenharmony_ci first_col_width = find_longest_name(json_diff_report) 351a8c51b3fSopenharmony_ci first_col_width = max( 352a8c51b3fSopenharmony_ci first_col_width, 353a8c51b3fSopenharmony_ci len('Benchmark')) 354a8c51b3fSopenharmony_ci first_col_width += len(UTEST_COL_NAME) 355a8c51b3fSopenharmony_ci first_line = "{:<{}s}Time CPU Time Old Time New CPU Old CPU New".format( 356a8c51b3fSopenharmony_ci 'Benchmark', 12 + first_col_width) 357a8c51b3fSopenharmony_ci output_strs = [first_line, '-' * len(first_line)] 358a8c51b3fSopenharmony_ci 359a8c51b3fSopenharmony_ci fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}" 360a8c51b3fSopenharmony_ci for benchmark in json_diff_report: 361a8c51b3fSopenharmony_ci # *If* we were asked to only include aggregates, 362a8c51b3fSopenharmony_ci # and if it is non-aggregate, then don't print it. 363a8c51b3fSopenharmony_ci if not include_aggregates_only or not 'run_type' in benchmark or benchmark['run_type'] == 'aggregate': 364a8c51b3fSopenharmony_ci for measurement in benchmark['measurements']: 365a8c51b3fSopenharmony_ci output_strs += [color_format(use_color, 366a8c51b3fSopenharmony_ci fmt_str, 367a8c51b3fSopenharmony_ci BC_HEADER, 368a8c51b3fSopenharmony_ci benchmark['name'], 369a8c51b3fSopenharmony_ci first_col_width, 370a8c51b3fSopenharmony_ci get_color(measurement['time']), 371a8c51b3fSopenharmony_ci measurement['time'], 372a8c51b3fSopenharmony_ci get_color(measurement['cpu']), 373a8c51b3fSopenharmony_ci measurement['cpu'], 374a8c51b3fSopenharmony_ci measurement['real_time'], 375a8c51b3fSopenharmony_ci measurement['real_time_other'], 376a8c51b3fSopenharmony_ci measurement['cpu_time'], 377a8c51b3fSopenharmony_ci measurement['cpu_time_other'], 378a8c51b3fSopenharmony_ci endc=BC_ENDC)] 379a8c51b3fSopenharmony_ci 380a8c51b3fSopenharmony_ci # After processing the measurements, if requested and 381a8c51b3fSopenharmony_ci # if applicable (e.g. u-test exists for given benchmark), 382a8c51b3fSopenharmony_ci # print the U test. 383a8c51b3fSopenharmony_ci if utest and benchmark['utest']: 384a8c51b3fSopenharmony_ci output_strs += print_utest(benchmark['name'], 385a8c51b3fSopenharmony_ci benchmark['utest'], 386a8c51b3fSopenharmony_ci utest_alpha=utest_alpha, 387a8c51b3fSopenharmony_ci first_col_width=first_col_width, 388a8c51b3fSopenharmony_ci use_color=use_color) 389a8c51b3fSopenharmony_ci 390a8c51b3fSopenharmony_ci return output_strs 391a8c51b3fSopenharmony_ci 392a8c51b3fSopenharmony_ci 393a8c51b3fSopenharmony_ci############################################################################### 394a8c51b3fSopenharmony_ci# Unit tests 395a8c51b3fSopenharmony_ci 396a8c51b3fSopenharmony_ci 397a8c51b3fSopenharmony_ciclass TestGetUniqueBenchmarkNames(unittest.TestCase): 398a8c51b3fSopenharmony_ci def load_results(self): 399a8c51b3fSopenharmony_ci import json 400a8c51b3fSopenharmony_ci testInputs = os.path.join( 401a8c51b3fSopenharmony_ci os.path.dirname( 402a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 403a8c51b3fSopenharmony_ci 'Inputs') 404a8c51b3fSopenharmony_ci testOutput = os.path.join(testInputs, 'test3_run0.json') 405a8c51b3fSopenharmony_ci with open(testOutput, 'r') as f: 406a8c51b3fSopenharmony_ci json = json.load(f) 407a8c51b3fSopenharmony_ci return json 408a8c51b3fSopenharmony_ci 409a8c51b3fSopenharmony_ci def test_basic(self): 410a8c51b3fSopenharmony_ci expect_lines = [ 411a8c51b3fSopenharmony_ci 'BM_One', 412a8c51b3fSopenharmony_ci 'BM_Two', 413a8c51b3fSopenharmony_ci 'short', # These two are not sorted 414a8c51b3fSopenharmony_ci 'medium', # These two are not sorted 415a8c51b3fSopenharmony_ci ] 416a8c51b3fSopenharmony_ci json = self.load_results() 417a8c51b3fSopenharmony_ci output_lines = get_unique_benchmark_names(json) 418a8c51b3fSopenharmony_ci print("\n") 419a8c51b3fSopenharmony_ci print("\n".join(output_lines)) 420a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 421a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 422a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], output_lines[i]) 423a8c51b3fSopenharmony_ci 424a8c51b3fSopenharmony_ci 425a8c51b3fSopenharmony_ciclass TestReportDifference(unittest.TestCase): 426a8c51b3fSopenharmony_ci @classmethod 427a8c51b3fSopenharmony_ci def setUpClass(cls): 428a8c51b3fSopenharmony_ci def load_results(): 429a8c51b3fSopenharmony_ci import json 430a8c51b3fSopenharmony_ci testInputs = os.path.join( 431a8c51b3fSopenharmony_ci os.path.dirname( 432a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 433a8c51b3fSopenharmony_ci 'Inputs') 434a8c51b3fSopenharmony_ci testOutput1 = os.path.join(testInputs, 'test1_run1.json') 435a8c51b3fSopenharmony_ci testOutput2 = os.path.join(testInputs, 'test1_run2.json') 436a8c51b3fSopenharmony_ci with open(testOutput1, 'r') as f: 437a8c51b3fSopenharmony_ci json1 = json.load(f) 438a8c51b3fSopenharmony_ci with open(testOutput2, 'r') as f: 439a8c51b3fSopenharmony_ci json2 = json.load(f) 440a8c51b3fSopenharmony_ci return json1, json2 441a8c51b3fSopenharmony_ci 442a8c51b3fSopenharmony_ci json1, json2 = load_results() 443a8c51b3fSopenharmony_ci cls.json_diff_report = get_difference_report(json1, json2) 444a8c51b3fSopenharmony_ci 445a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing(self): 446a8c51b3fSopenharmony_ci expect_lines = [ 447a8c51b3fSopenharmony_ci ['BM_SameTimes', '+0.0000', '+0.0000', '10', '10', '10', '10'], 448a8c51b3fSopenharmony_ci ['BM_2xFaster', '-0.5000', '-0.5000', '50', '25', '50', '25'], 449a8c51b3fSopenharmony_ci ['BM_2xSlower', '+1.0000', '+1.0000', '50', '100', '50', '100'], 450a8c51b3fSopenharmony_ci ['BM_1PercentFaster', '-0.0100', '-0.0100', '100', '99', '100', '99'], 451a8c51b3fSopenharmony_ci ['BM_1PercentSlower', '+0.0100', '+0.0100', '100', '101', '100', '101'], 452a8c51b3fSopenharmony_ci ['BM_10PercentFaster', '-0.1000', '-0.1000', '100', '90', '100', '90'], 453a8c51b3fSopenharmony_ci ['BM_10PercentSlower', '+0.1000', '+0.1000', '100', '110', '100', '110'], 454a8c51b3fSopenharmony_ci ['BM_100xSlower', '+99.0000', '+99.0000', 455a8c51b3fSopenharmony_ci '100', '10000', '100', '10000'], 456a8c51b3fSopenharmony_ci ['BM_100xFaster', '-0.9900', '-0.9900', 457a8c51b3fSopenharmony_ci '10000', '100', '10000', '100'], 458a8c51b3fSopenharmony_ci ['BM_10PercentCPUToTime', '+0.1000', 459a8c51b3fSopenharmony_ci '-0.1000', '100', '110', '100', '90'], 460a8c51b3fSopenharmony_ci ['BM_ThirdFaster', '-0.3333', '-0.3334', '100', '67', '100', '67'], 461a8c51b3fSopenharmony_ci ['BM_NotBadTimeUnit', '-0.9000', '+0.2000', '0', '0', '0', '1'], 462a8c51b3fSopenharmony_ci ['BM_hasLabel', '+0.0000', '+0.0000', '1', '1', '1', '1'], 463a8c51b3fSopenharmony_ci ['OVERALL_GEOMEAN', '-0.8113', '-0.7779', '0', '0', '0', '0'] 464a8c51b3fSopenharmony_ci ] 465a8c51b3fSopenharmony_ci output_lines_with_header = print_difference_report( 466a8c51b3fSopenharmony_ci self.json_diff_report, use_color=False) 467a8c51b3fSopenharmony_ci output_lines = output_lines_with_header[2:] 468a8c51b3fSopenharmony_ci print("\n") 469a8c51b3fSopenharmony_ci print("\n".join(output_lines_with_header)) 470a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 471a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 472a8c51b3fSopenharmony_ci parts = [x for x in output_lines[i].split(' ') if x] 473a8c51b3fSopenharmony_ci self.assertEqual(len(parts), 7) 474a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], parts) 475a8c51b3fSopenharmony_ci 476a8c51b3fSopenharmony_ci def test_json_diff_report_output(self): 477a8c51b3fSopenharmony_ci expected_output = [ 478a8c51b3fSopenharmony_ci { 479a8c51b3fSopenharmony_ci 'name': 'BM_SameTimes', 480a8c51b3fSopenharmony_ci 'label': '', 481a8c51b3fSopenharmony_ci 'measurements': [{'time': 0.0000, 'cpu': 0.0000, 482a8c51b3fSopenharmony_ci 'real_time': 10, 'real_time_other': 10, 483a8c51b3fSopenharmony_ci 'cpu_time': 10, 'cpu_time_other': 10}], 484a8c51b3fSopenharmony_ci 'time_unit': 'ns', 485a8c51b3fSopenharmony_ci 'utest': {} 486a8c51b3fSopenharmony_ci }, 487a8c51b3fSopenharmony_ci { 488a8c51b3fSopenharmony_ci 'name': 'BM_2xFaster', 489a8c51b3fSopenharmony_ci 'label': '', 490a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.5000, 'cpu': -0.5000, 491a8c51b3fSopenharmony_ci 'real_time': 50, 'real_time_other': 25, 492a8c51b3fSopenharmony_ci 'cpu_time': 50, 'cpu_time_other': 25}], 493a8c51b3fSopenharmony_ci 'time_unit': 'ns', 494a8c51b3fSopenharmony_ci 'utest': {} 495a8c51b3fSopenharmony_ci }, 496a8c51b3fSopenharmony_ci { 497a8c51b3fSopenharmony_ci 'name': 'BM_2xSlower', 498a8c51b3fSopenharmony_ci 'label': '', 499a8c51b3fSopenharmony_ci 'measurements': [{'time': 1.0000, 'cpu': 1.0000, 500a8c51b3fSopenharmony_ci 'real_time': 50, 'real_time_other': 100, 501a8c51b3fSopenharmony_ci 'cpu_time': 50, 'cpu_time_other': 100}], 502a8c51b3fSopenharmony_ci 'time_unit': 'ns', 503a8c51b3fSopenharmony_ci 'utest': {} 504a8c51b3fSopenharmony_ci }, 505a8c51b3fSopenharmony_ci { 506a8c51b3fSopenharmony_ci 'name': 'BM_1PercentFaster', 507a8c51b3fSopenharmony_ci 'label': '', 508a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.0100, 'cpu': -0.0100, 509a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 98.9999999, 510a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 98.9999999}], 511a8c51b3fSopenharmony_ci 'time_unit': 'ns', 512a8c51b3fSopenharmony_ci 'utest': {} 513a8c51b3fSopenharmony_ci }, 514a8c51b3fSopenharmony_ci { 515a8c51b3fSopenharmony_ci 'name': 'BM_1PercentSlower', 516a8c51b3fSopenharmony_ci 'label': '', 517a8c51b3fSopenharmony_ci 'measurements': [{'time': 0.0100, 'cpu': 0.0100, 518a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 101, 519a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 101}], 520a8c51b3fSopenharmony_ci 'time_unit': 'ns', 521a8c51b3fSopenharmony_ci 'utest': {} 522a8c51b3fSopenharmony_ci }, 523a8c51b3fSopenharmony_ci { 524a8c51b3fSopenharmony_ci 'name': 'BM_10PercentFaster', 525a8c51b3fSopenharmony_ci 'label': '', 526a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.1000, 'cpu': -0.1000, 527a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 90, 528a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 90}], 529a8c51b3fSopenharmony_ci 'time_unit': 'ns', 530a8c51b3fSopenharmony_ci 'utest': {} 531a8c51b3fSopenharmony_ci }, 532a8c51b3fSopenharmony_ci { 533a8c51b3fSopenharmony_ci 'name': 'BM_10PercentSlower', 534a8c51b3fSopenharmony_ci 'label': '', 535a8c51b3fSopenharmony_ci 'measurements': [{'time': 0.1000, 'cpu': 0.1000, 536a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 110, 537a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 110}], 538a8c51b3fSopenharmony_ci 'time_unit': 'ns', 539a8c51b3fSopenharmony_ci 'utest': {} 540a8c51b3fSopenharmony_ci }, 541a8c51b3fSopenharmony_ci { 542a8c51b3fSopenharmony_ci 'name': 'BM_100xSlower', 543a8c51b3fSopenharmony_ci 'label': '', 544a8c51b3fSopenharmony_ci 'measurements': [{'time': 99.0000, 'cpu': 99.0000, 545a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 10000, 546a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 10000}], 547a8c51b3fSopenharmony_ci 'time_unit': 'ns', 548a8c51b3fSopenharmony_ci 'utest': {} 549a8c51b3fSopenharmony_ci }, 550a8c51b3fSopenharmony_ci { 551a8c51b3fSopenharmony_ci 'name': 'BM_100xFaster', 552a8c51b3fSopenharmony_ci 'label': '', 553a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.9900, 'cpu': -0.9900, 554a8c51b3fSopenharmony_ci 'real_time': 10000, 'real_time_other': 100, 555a8c51b3fSopenharmony_ci 'cpu_time': 10000, 'cpu_time_other': 100}], 556a8c51b3fSopenharmony_ci 'time_unit': 'ns', 557a8c51b3fSopenharmony_ci 'utest': {} 558a8c51b3fSopenharmony_ci }, 559a8c51b3fSopenharmony_ci { 560a8c51b3fSopenharmony_ci 'name': 'BM_10PercentCPUToTime', 561a8c51b3fSopenharmony_ci 'label': '', 562a8c51b3fSopenharmony_ci 'measurements': [{'time': 0.1000, 'cpu': -0.1000, 563a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 110, 564a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 90}], 565a8c51b3fSopenharmony_ci 'time_unit': 'ns', 566a8c51b3fSopenharmony_ci 'utest': {} 567a8c51b3fSopenharmony_ci }, 568a8c51b3fSopenharmony_ci { 569a8c51b3fSopenharmony_ci 'name': 'BM_ThirdFaster', 570a8c51b3fSopenharmony_ci 'label': '', 571a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.3333, 'cpu': -0.3334, 572a8c51b3fSopenharmony_ci 'real_time': 100, 'real_time_other': 67, 573a8c51b3fSopenharmony_ci 'cpu_time': 100, 'cpu_time_other': 67}], 574a8c51b3fSopenharmony_ci 'time_unit': 'ns', 575a8c51b3fSopenharmony_ci 'utest': {} 576a8c51b3fSopenharmony_ci }, 577a8c51b3fSopenharmony_ci { 578a8c51b3fSopenharmony_ci 'name': 'BM_NotBadTimeUnit', 579a8c51b3fSopenharmony_ci 'label': '', 580a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.9000, 'cpu': 0.2000, 581a8c51b3fSopenharmony_ci 'real_time': 0.4, 'real_time_other': 0.04, 582a8c51b3fSopenharmony_ci 'cpu_time': 0.5, 'cpu_time_other': 0.6}], 583a8c51b3fSopenharmony_ci 'time_unit': 's', 584a8c51b3fSopenharmony_ci 'utest': {} 585a8c51b3fSopenharmony_ci }, 586a8c51b3fSopenharmony_ci { 587a8c51b3fSopenharmony_ci 'name': 'BM_hasLabel', 588a8c51b3fSopenharmony_ci 'label': 'a label', 589a8c51b3fSopenharmony_ci 'measurements': [{'time': 0.0000, 'cpu': 0.0000, 590a8c51b3fSopenharmony_ci 'real_time': 1, 'real_time_other': 1, 591a8c51b3fSopenharmony_ci 'cpu_time': 1, 'cpu_time_other': 1}], 592a8c51b3fSopenharmony_ci 'time_unit': 's', 593a8c51b3fSopenharmony_ci 'utest': {} 594a8c51b3fSopenharmony_ci }, 595a8c51b3fSopenharmony_ci { 596a8c51b3fSopenharmony_ci 'name': 'OVERALL_GEOMEAN', 597a8c51b3fSopenharmony_ci 'label': '', 598a8c51b3fSopenharmony_ci 'measurements': [{'real_time': 3.1622776601683826e-06, 'cpu_time': 3.2130844755623912e-06, 599a8c51b3fSopenharmony_ci 'real_time_other': 1.9768988699420897e-07, 'cpu_time_other': 2.397447755209533e-07, 600a8c51b3fSopenharmony_ci 'time': -0.8112976497120911, 'cpu': -0.7778551721181174}], 601a8c51b3fSopenharmony_ci 'time_unit': 's', 602a8c51b3fSopenharmony_ci 'run_type': 'aggregate', 603a8c51b3fSopenharmony_ci 'aggregate_name': 'geomean', 'utest': {} 604a8c51b3fSopenharmony_ci }, 605a8c51b3fSopenharmony_ci ] 606a8c51b3fSopenharmony_ci self.assertEqual(len(self.json_diff_report), len(expected_output)) 607a8c51b3fSopenharmony_ci for out, expected in zip( 608a8c51b3fSopenharmony_ci self.json_diff_report, expected_output): 609a8c51b3fSopenharmony_ci self.assertEqual(out['name'], expected['name']) 610a8c51b3fSopenharmony_ci self.assertEqual(out['label'], expected['label']) 611a8c51b3fSopenharmony_ci self.assertEqual(out['time_unit'], expected['time_unit']) 612a8c51b3fSopenharmony_ci assert_utest(self, out, expected) 613a8c51b3fSopenharmony_ci assert_measurements(self, out, expected) 614a8c51b3fSopenharmony_ci 615a8c51b3fSopenharmony_ci 616a8c51b3fSopenharmony_ciclass TestReportDifferenceBetweenFamilies(unittest.TestCase): 617a8c51b3fSopenharmony_ci @classmethod 618a8c51b3fSopenharmony_ci def setUpClass(cls): 619a8c51b3fSopenharmony_ci def load_result(): 620a8c51b3fSopenharmony_ci import json 621a8c51b3fSopenharmony_ci testInputs = os.path.join( 622a8c51b3fSopenharmony_ci os.path.dirname( 623a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 624a8c51b3fSopenharmony_ci 'Inputs') 625a8c51b3fSopenharmony_ci testOutput = os.path.join(testInputs, 'test2_run.json') 626a8c51b3fSopenharmony_ci with open(testOutput, 'r') as f: 627a8c51b3fSopenharmony_ci json = json.load(f) 628a8c51b3fSopenharmony_ci return json 629a8c51b3fSopenharmony_ci 630a8c51b3fSopenharmony_ci json = load_result() 631a8c51b3fSopenharmony_ci json1 = filter_benchmark(json, "BM_Z.ro", ".") 632a8c51b3fSopenharmony_ci json2 = filter_benchmark(json, "BM_O.e", ".") 633a8c51b3fSopenharmony_ci cls.json_diff_report = get_difference_report(json1, json2) 634a8c51b3fSopenharmony_ci 635a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing(self): 636a8c51b3fSopenharmony_ci expect_lines = [ 637a8c51b3fSopenharmony_ci ['.', '-0.5000', '-0.5000', '10', '5', '10', '5'], 638a8c51b3fSopenharmony_ci ['./4', '-0.5000', '-0.5000', '40', '20', '40', '20'], 639a8c51b3fSopenharmony_ci ['Prefix/.', '-0.5000', '-0.5000', '20', '10', '20', '10'], 640a8c51b3fSopenharmony_ci ['Prefix/./3', '-0.5000', '-0.5000', '30', '15', '30', '15'], 641a8c51b3fSopenharmony_ci ['OVERALL_GEOMEAN', '-0.5000', '-0.5000', '0', '0', '0', '0'] 642a8c51b3fSopenharmony_ci ] 643a8c51b3fSopenharmony_ci output_lines_with_header = print_difference_report( 644a8c51b3fSopenharmony_ci self.json_diff_report, use_color=False) 645a8c51b3fSopenharmony_ci output_lines = output_lines_with_header[2:] 646a8c51b3fSopenharmony_ci print("\n") 647a8c51b3fSopenharmony_ci print("\n".join(output_lines_with_header)) 648a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 649a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 650a8c51b3fSopenharmony_ci parts = [x for x in output_lines[i].split(' ') if x] 651a8c51b3fSopenharmony_ci self.assertEqual(len(parts), 7) 652a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], parts) 653a8c51b3fSopenharmony_ci 654a8c51b3fSopenharmony_ci def test_json_diff_report(self): 655a8c51b3fSopenharmony_ci expected_output = [ 656a8c51b3fSopenharmony_ci { 657a8c51b3fSopenharmony_ci 'name': u'.', 658a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 10, 'real_time_other': 5, 'cpu_time': 10, 'cpu_time_other': 5}], 659a8c51b3fSopenharmony_ci 'time_unit': 'ns', 660a8c51b3fSopenharmony_ci 'utest': {} 661a8c51b3fSopenharmony_ci }, 662a8c51b3fSopenharmony_ci { 663a8c51b3fSopenharmony_ci 'name': u'./4', 664a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 40, 'real_time_other': 20, 'cpu_time': 40, 'cpu_time_other': 20}], 665a8c51b3fSopenharmony_ci 'time_unit': 'ns', 666a8c51b3fSopenharmony_ci 'utest': {}, 667a8c51b3fSopenharmony_ci }, 668a8c51b3fSopenharmony_ci { 669a8c51b3fSopenharmony_ci 'name': u'Prefix/.', 670a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 20, 'real_time_other': 10, 'cpu_time': 20, 'cpu_time_other': 10}], 671a8c51b3fSopenharmony_ci 'time_unit': 'ns', 672a8c51b3fSopenharmony_ci 'utest': {} 673a8c51b3fSopenharmony_ci }, 674a8c51b3fSopenharmony_ci { 675a8c51b3fSopenharmony_ci 'name': u'Prefix/./3', 676a8c51b3fSopenharmony_ci 'measurements': [{'time': -0.5, 'cpu': -0.5, 'real_time': 30, 'real_time_other': 15, 'cpu_time': 30, 'cpu_time_other': 15}], 677a8c51b3fSopenharmony_ci 'time_unit': 'ns', 678a8c51b3fSopenharmony_ci 'utest': {} 679a8c51b3fSopenharmony_ci }, 680a8c51b3fSopenharmony_ci { 681a8c51b3fSopenharmony_ci 'name': 'OVERALL_GEOMEAN', 682a8c51b3fSopenharmony_ci 'measurements': [{'real_time': 2.213363839400641e-08, 'cpu_time': 2.213363839400641e-08, 683a8c51b3fSopenharmony_ci 'real_time_other': 1.1066819197003185e-08, 'cpu_time_other': 1.1066819197003185e-08, 684a8c51b3fSopenharmony_ci 'time': -0.5000000000000009, 'cpu': -0.5000000000000009}], 685a8c51b3fSopenharmony_ci 'time_unit': 's', 686a8c51b3fSopenharmony_ci 'run_type': 'aggregate', 687a8c51b3fSopenharmony_ci 'aggregate_name': 'geomean', 688a8c51b3fSopenharmony_ci 'utest': {} 689a8c51b3fSopenharmony_ci } 690a8c51b3fSopenharmony_ci ] 691a8c51b3fSopenharmony_ci self.assertEqual(len(self.json_diff_report), len(expected_output)) 692a8c51b3fSopenharmony_ci for out, expected in zip( 693a8c51b3fSopenharmony_ci self.json_diff_report, expected_output): 694a8c51b3fSopenharmony_ci self.assertEqual(out['name'], expected['name']) 695a8c51b3fSopenharmony_ci self.assertEqual(out['time_unit'], expected['time_unit']) 696a8c51b3fSopenharmony_ci assert_utest(self, out, expected) 697a8c51b3fSopenharmony_ci assert_measurements(self, out, expected) 698a8c51b3fSopenharmony_ci 699a8c51b3fSopenharmony_ci 700a8c51b3fSopenharmony_ciclass TestReportDifferenceWithUTest(unittest.TestCase): 701a8c51b3fSopenharmony_ci @classmethod 702a8c51b3fSopenharmony_ci def setUpClass(cls): 703a8c51b3fSopenharmony_ci def load_results(): 704a8c51b3fSopenharmony_ci import json 705a8c51b3fSopenharmony_ci testInputs = os.path.join( 706a8c51b3fSopenharmony_ci os.path.dirname( 707a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 708a8c51b3fSopenharmony_ci 'Inputs') 709a8c51b3fSopenharmony_ci testOutput1 = os.path.join(testInputs, 'test3_run0.json') 710a8c51b3fSopenharmony_ci testOutput2 = os.path.join(testInputs, 'test3_run1.json') 711a8c51b3fSopenharmony_ci with open(testOutput1, 'r') as f: 712a8c51b3fSopenharmony_ci json1 = json.load(f) 713a8c51b3fSopenharmony_ci with open(testOutput2, 'r') as f: 714a8c51b3fSopenharmony_ci json2 = json.load(f) 715a8c51b3fSopenharmony_ci return json1, json2 716a8c51b3fSopenharmony_ci 717a8c51b3fSopenharmony_ci json1, json2 = load_results() 718a8c51b3fSopenharmony_ci cls.json_diff_report = get_difference_report( 719a8c51b3fSopenharmony_ci json1, json2, utest=True) 720a8c51b3fSopenharmony_ci 721a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing(self): 722a8c51b3fSopenharmony_ci expect_lines = [ 723a8c51b3fSopenharmony_ci ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], 724a8c51b3fSopenharmony_ci ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'], 725a8c51b3fSopenharmony_ci ['BM_Two', '-0.1250', '-0.1628', '8', '7', '86', '72'], 726a8c51b3fSopenharmony_ci ['BM_Two_pvalue', 727a8c51b3fSopenharmony_ci '1.0000', 728a8c51b3fSopenharmony_ci '0.6667', 729a8c51b3fSopenharmony_ci 'U', 730a8c51b3fSopenharmony_ci 'Test,', 731a8c51b3fSopenharmony_ci 'Repetitions:', 732a8c51b3fSopenharmony_ci '2', 733a8c51b3fSopenharmony_ci 'vs', 734a8c51b3fSopenharmony_ci '2.', 735a8c51b3fSopenharmony_ci 'WARNING:', 736a8c51b3fSopenharmony_ci 'Results', 737a8c51b3fSopenharmony_ci 'unreliable!', 738a8c51b3fSopenharmony_ci '9+', 739a8c51b3fSopenharmony_ci 'repetitions', 740a8c51b3fSopenharmony_ci 'recommended.'], 741a8c51b3fSopenharmony_ci ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'], 742a8c51b3fSopenharmony_ci ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'], 743a8c51b3fSopenharmony_ci ['short_pvalue', 744a8c51b3fSopenharmony_ci '0.7671', 745a8c51b3fSopenharmony_ci '0.2000', 746a8c51b3fSopenharmony_ci 'U', 747a8c51b3fSopenharmony_ci 'Test,', 748a8c51b3fSopenharmony_ci 'Repetitions:', 749a8c51b3fSopenharmony_ci '2', 750a8c51b3fSopenharmony_ci 'vs', 751a8c51b3fSopenharmony_ci '3.', 752a8c51b3fSopenharmony_ci 'WARNING:', 753a8c51b3fSopenharmony_ci 'Results', 754a8c51b3fSopenharmony_ci 'unreliable!', 755a8c51b3fSopenharmony_ci '9+', 756a8c51b3fSopenharmony_ci 'repetitions', 757a8c51b3fSopenharmony_ci 'recommended.'], 758a8c51b3fSopenharmony_ci ['medium', '-0.3750', '-0.3375', '8', '5', '80', '53'], 759a8c51b3fSopenharmony_ci ['OVERALL_GEOMEAN', '+1.6405', '-0.6985', '0', '0', '0', '0'] 760a8c51b3fSopenharmony_ci ] 761a8c51b3fSopenharmony_ci output_lines_with_header = print_difference_report( 762a8c51b3fSopenharmony_ci self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False) 763a8c51b3fSopenharmony_ci output_lines = output_lines_with_header[2:] 764a8c51b3fSopenharmony_ci print("\n") 765a8c51b3fSopenharmony_ci print("\n".join(output_lines_with_header)) 766a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 767a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 768a8c51b3fSopenharmony_ci parts = [x for x in output_lines[i].split(' ') if x] 769a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], parts) 770a8c51b3fSopenharmony_ci 771a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing_aggregates_only(self): 772a8c51b3fSopenharmony_ci expect_lines = [ 773a8c51b3fSopenharmony_ci ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], 774a8c51b3fSopenharmony_ci ['BM_Two_pvalue', 775a8c51b3fSopenharmony_ci '1.0000', 776a8c51b3fSopenharmony_ci '0.6667', 777a8c51b3fSopenharmony_ci 'U', 778a8c51b3fSopenharmony_ci 'Test,', 779a8c51b3fSopenharmony_ci 'Repetitions:', 780a8c51b3fSopenharmony_ci '2', 781a8c51b3fSopenharmony_ci 'vs', 782a8c51b3fSopenharmony_ci '2.', 783a8c51b3fSopenharmony_ci 'WARNING:', 784a8c51b3fSopenharmony_ci 'Results', 785a8c51b3fSopenharmony_ci 'unreliable!', 786a8c51b3fSopenharmony_ci '9+', 787a8c51b3fSopenharmony_ci 'repetitions', 788a8c51b3fSopenharmony_ci 'recommended.'], 789a8c51b3fSopenharmony_ci ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'], 790a8c51b3fSopenharmony_ci ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'], 791a8c51b3fSopenharmony_ci ['short_pvalue', 792a8c51b3fSopenharmony_ci '0.7671', 793a8c51b3fSopenharmony_ci '0.2000', 794a8c51b3fSopenharmony_ci 'U', 795a8c51b3fSopenharmony_ci 'Test,', 796a8c51b3fSopenharmony_ci 'Repetitions:', 797a8c51b3fSopenharmony_ci '2', 798a8c51b3fSopenharmony_ci 'vs', 799a8c51b3fSopenharmony_ci '3.', 800a8c51b3fSopenharmony_ci 'WARNING:', 801a8c51b3fSopenharmony_ci 'Results', 802a8c51b3fSopenharmony_ci 'unreliable!', 803a8c51b3fSopenharmony_ci '9+', 804a8c51b3fSopenharmony_ci 'repetitions', 805a8c51b3fSopenharmony_ci 'recommended.'], 806a8c51b3fSopenharmony_ci ['OVERALL_GEOMEAN', '+1.6405', '-0.6985', '0', '0', '0', '0'] 807a8c51b3fSopenharmony_ci ] 808a8c51b3fSopenharmony_ci output_lines_with_header = print_difference_report( 809a8c51b3fSopenharmony_ci self.json_diff_report, include_aggregates_only=True, utest=True, utest_alpha=0.05, use_color=False) 810a8c51b3fSopenharmony_ci output_lines = output_lines_with_header[2:] 811a8c51b3fSopenharmony_ci print("\n") 812a8c51b3fSopenharmony_ci print("\n".join(output_lines_with_header)) 813a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 814a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 815a8c51b3fSopenharmony_ci parts = [x for x in output_lines[i].split(' ') if x] 816a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], parts) 817a8c51b3fSopenharmony_ci 818a8c51b3fSopenharmony_ci def test_json_diff_report(self): 819a8c51b3fSopenharmony_ci expected_output = [ 820a8c51b3fSopenharmony_ci { 821a8c51b3fSopenharmony_ci 'name': u'BM_One', 822a8c51b3fSopenharmony_ci 'measurements': [ 823a8c51b3fSopenharmony_ci {'time': -0.1, 824a8c51b3fSopenharmony_ci 'cpu': 0.1, 825a8c51b3fSopenharmony_ci 'real_time': 10, 826a8c51b3fSopenharmony_ci 'real_time_other': 9, 827a8c51b3fSopenharmony_ci 'cpu_time': 100, 828a8c51b3fSopenharmony_ci 'cpu_time_other': 110} 829a8c51b3fSopenharmony_ci ], 830a8c51b3fSopenharmony_ci 'time_unit': 'ns', 831a8c51b3fSopenharmony_ci 'utest': {} 832a8c51b3fSopenharmony_ci }, 833a8c51b3fSopenharmony_ci { 834a8c51b3fSopenharmony_ci 'name': u'BM_Two', 835a8c51b3fSopenharmony_ci 'measurements': [ 836a8c51b3fSopenharmony_ci {'time': 0.1111111111111111, 837a8c51b3fSopenharmony_ci 'cpu': -0.011111111111111112, 838a8c51b3fSopenharmony_ci 'real_time': 9, 839a8c51b3fSopenharmony_ci 'real_time_other': 10, 840a8c51b3fSopenharmony_ci 'cpu_time': 90, 841a8c51b3fSopenharmony_ci 'cpu_time_other': 89}, 842a8c51b3fSopenharmony_ci {'time': -0.125, 'cpu': -0.16279069767441862, 'real_time': 8, 843a8c51b3fSopenharmony_ci 'real_time_other': 7, 'cpu_time': 86, 'cpu_time_other': 72} 844a8c51b3fSopenharmony_ci ], 845a8c51b3fSopenharmony_ci 'time_unit': 'ns', 846a8c51b3fSopenharmony_ci 'utest': { 847a8c51b3fSopenharmony_ci 'have_optimal_repetitions': False, 'cpu_pvalue': 0.6666666666666666, 'time_pvalue': 1.0 848a8c51b3fSopenharmony_ci } 849a8c51b3fSopenharmony_ci }, 850a8c51b3fSopenharmony_ci { 851a8c51b3fSopenharmony_ci 'name': u'short', 852a8c51b3fSopenharmony_ci 'measurements': [ 853a8c51b3fSopenharmony_ci {'time': -0.125, 854a8c51b3fSopenharmony_ci 'cpu': -0.0625, 855a8c51b3fSopenharmony_ci 'real_time': 8, 856a8c51b3fSopenharmony_ci 'real_time_other': 7, 857a8c51b3fSopenharmony_ci 'cpu_time': 80, 858a8c51b3fSopenharmony_ci 'cpu_time_other': 75}, 859a8c51b3fSopenharmony_ci {'time': -0.4325, 860a8c51b3fSopenharmony_ci 'cpu': -0.13506493506493514, 861a8c51b3fSopenharmony_ci 'real_time': 8, 862a8c51b3fSopenharmony_ci 'real_time_other': 4.54, 863a8c51b3fSopenharmony_ci 'cpu_time': 77, 864a8c51b3fSopenharmony_ci 'cpu_time_other': 66.6} 865a8c51b3fSopenharmony_ci ], 866a8c51b3fSopenharmony_ci 'time_unit': 'ns', 867a8c51b3fSopenharmony_ci 'utest': { 868a8c51b3fSopenharmony_ci 'have_optimal_repetitions': False, 'cpu_pvalue': 0.2, 'time_pvalue': 0.7670968684102772 869a8c51b3fSopenharmony_ci } 870a8c51b3fSopenharmony_ci }, 871a8c51b3fSopenharmony_ci { 872a8c51b3fSopenharmony_ci 'name': u'medium', 873a8c51b3fSopenharmony_ci 'measurements': [ 874a8c51b3fSopenharmony_ci {'time': -0.375, 875a8c51b3fSopenharmony_ci 'cpu': -0.3375, 876a8c51b3fSopenharmony_ci 'real_time': 8, 877a8c51b3fSopenharmony_ci 'real_time_other': 5, 878a8c51b3fSopenharmony_ci 'cpu_time': 80, 879a8c51b3fSopenharmony_ci 'cpu_time_other': 53} 880a8c51b3fSopenharmony_ci ], 881a8c51b3fSopenharmony_ci 'time_unit': 'ns', 882a8c51b3fSopenharmony_ci 'utest': {} 883a8c51b3fSopenharmony_ci }, 884a8c51b3fSopenharmony_ci { 885a8c51b3fSopenharmony_ci 'name': 'OVERALL_GEOMEAN', 886a8c51b3fSopenharmony_ci 'measurements': [{'real_time': 8.48528137423858e-09, 'cpu_time': 8.441336246629233e-08, 887a8c51b3fSopenharmony_ci 'real_time_other': 2.2405267593145244e-08, 'cpu_time_other': 2.5453661413660466e-08, 888a8c51b3fSopenharmony_ci 'time': 1.6404861082353634, 'cpu': -0.6984640740519662}], 889a8c51b3fSopenharmony_ci 'time_unit': 's', 890a8c51b3fSopenharmony_ci 'run_type': 'aggregate', 891a8c51b3fSopenharmony_ci 'aggregate_name': 'geomean', 892a8c51b3fSopenharmony_ci 'utest': {} 893a8c51b3fSopenharmony_ci } 894a8c51b3fSopenharmony_ci ] 895a8c51b3fSopenharmony_ci self.assertEqual(len(self.json_diff_report), len(expected_output)) 896a8c51b3fSopenharmony_ci for out, expected in zip( 897a8c51b3fSopenharmony_ci self.json_diff_report, expected_output): 898a8c51b3fSopenharmony_ci self.assertEqual(out['name'], expected['name']) 899a8c51b3fSopenharmony_ci self.assertEqual(out['time_unit'], expected['time_unit']) 900a8c51b3fSopenharmony_ci assert_utest(self, out, expected) 901a8c51b3fSopenharmony_ci assert_measurements(self, out, expected) 902a8c51b3fSopenharmony_ci 903a8c51b3fSopenharmony_ci 904a8c51b3fSopenharmony_ciclass TestReportDifferenceWithUTestWhileDisplayingAggregatesOnly( 905a8c51b3fSopenharmony_ci unittest.TestCase): 906a8c51b3fSopenharmony_ci @classmethod 907a8c51b3fSopenharmony_ci def setUpClass(cls): 908a8c51b3fSopenharmony_ci def load_results(): 909a8c51b3fSopenharmony_ci import json 910a8c51b3fSopenharmony_ci testInputs = os.path.join( 911a8c51b3fSopenharmony_ci os.path.dirname( 912a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 913a8c51b3fSopenharmony_ci 'Inputs') 914a8c51b3fSopenharmony_ci testOutput1 = os.path.join(testInputs, 'test3_run0.json') 915a8c51b3fSopenharmony_ci testOutput2 = os.path.join(testInputs, 'test3_run1.json') 916a8c51b3fSopenharmony_ci with open(testOutput1, 'r') as f: 917a8c51b3fSopenharmony_ci json1 = json.load(f) 918a8c51b3fSopenharmony_ci with open(testOutput2, 'r') as f: 919a8c51b3fSopenharmony_ci json2 = json.load(f) 920a8c51b3fSopenharmony_ci return json1, json2 921a8c51b3fSopenharmony_ci 922a8c51b3fSopenharmony_ci json1, json2 = load_results() 923a8c51b3fSopenharmony_ci cls.json_diff_report = get_difference_report( 924a8c51b3fSopenharmony_ci json1, json2, utest=True) 925a8c51b3fSopenharmony_ci 926a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing(self): 927a8c51b3fSopenharmony_ci expect_lines = [ 928a8c51b3fSopenharmony_ci ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'], 929a8c51b3fSopenharmony_ci ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'], 930a8c51b3fSopenharmony_ci ['BM_Two', '-0.1250', '-0.1628', '8', '7', '86', '72'], 931a8c51b3fSopenharmony_ci ['BM_Two_pvalue', 932a8c51b3fSopenharmony_ci '1.0000', 933a8c51b3fSopenharmony_ci '0.6667', 934a8c51b3fSopenharmony_ci 'U', 935a8c51b3fSopenharmony_ci 'Test,', 936a8c51b3fSopenharmony_ci 'Repetitions:', 937a8c51b3fSopenharmony_ci '2', 938a8c51b3fSopenharmony_ci 'vs', 939a8c51b3fSopenharmony_ci '2.', 940a8c51b3fSopenharmony_ci 'WARNING:', 941a8c51b3fSopenharmony_ci 'Results', 942a8c51b3fSopenharmony_ci 'unreliable!', 943a8c51b3fSopenharmony_ci '9+', 944a8c51b3fSopenharmony_ci 'repetitions', 945a8c51b3fSopenharmony_ci 'recommended.'], 946a8c51b3fSopenharmony_ci ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'], 947a8c51b3fSopenharmony_ci ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'], 948a8c51b3fSopenharmony_ci ['short_pvalue', 949a8c51b3fSopenharmony_ci '0.7671', 950a8c51b3fSopenharmony_ci '0.2000', 951a8c51b3fSopenharmony_ci 'U', 952a8c51b3fSopenharmony_ci 'Test,', 953a8c51b3fSopenharmony_ci 'Repetitions:', 954a8c51b3fSopenharmony_ci '2', 955a8c51b3fSopenharmony_ci 'vs', 956a8c51b3fSopenharmony_ci '3.', 957a8c51b3fSopenharmony_ci 'WARNING:', 958a8c51b3fSopenharmony_ci 'Results', 959a8c51b3fSopenharmony_ci 'unreliable!', 960a8c51b3fSopenharmony_ci '9+', 961a8c51b3fSopenharmony_ci 'repetitions', 962a8c51b3fSopenharmony_ci 'recommended.'], 963a8c51b3fSopenharmony_ci ['medium', '-0.3750', '-0.3375', '8', '5', '80', '53'], 964a8c51b3fSopenharmony_ci ['OVERALL_GEOMEAN', '+1.6405', '-0.6985', '0', '0', '0', '0'] 965a8c51b3fSopenharmony_ci ] 966a8c51b3fSopenharmony_ci output_lines_with_header = print_difference_report( 967a8c51b3fSopenharmony_ci self.json_diff_report, 968a8c51b3fSopenharmony_ci utest=True, utest_alpha=0.05, use_color=False) 969a8c51b3fSopenharmony_ci output_lines = output_lines_with_header[2:] 970a8c51b3fSopenharmony_ci print("\n") 971a8c51b3fSopenharmony_ci print("\n".join(output_lines_with_header)) 972a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 973a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 974a8c51b3fSopenharmony_ci parts = [x for x in output_lines[i].split(' ') if x] 975a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], parts) 976a8c51b3fSopenharmony_ci 977a8c51b3fSopenharmony_ci def test_json_diff_report(self): 978a8c51b3fSopenharmony_ci expected_output = [ 979a8c51b3fSopenharmony_ci { 980a8c51b3fSopenharmony_ci 'name': u'BM_One', 981a8c51b3fSopenharmony_ci 'measurements': [ 982a8c51b3fSopenharmony_ci {'time': -0.1, 983a8c51b3fSopenharmony_ci 'cpu': 0.1, 984a8c51b3fSopenharmony_ci 'real_time': 10, 985a8c51b3fSopenharmony_ci 'real_time_other': 9, 986a8c51b3fSopenharmony_ci 'cpu_time': 100, 987a8c51b3fSopenharmony_ci 'cpu_time_other': 110} 988a8c51b3fSopenharmony_ci ], 989a8c51b3fSopenharmony_ci 'time_unit': 'ns', 990a8c51b3fSopenharmony_ci 'utest': {} 991a8c51b3fSopenharmony_ci }, 992a8c51b3fSopenharmony_ci { 993a8c51b3fSopenharmony_ci 'name': u'BM_Two', 994a8c51b3fSopenharmony_ci 'measurements': [ 995a8c51b3fSopenharmony_ci {'time': 0.1111111111111111, 996a8c51b3fSopenharmony_ci 'cpu': -0.011111111111111112, 997a8c51b3fSopenharmony_ci 'real_time': 9, 998a8c51b3fSopenharmony_ci 'real_time_other': 10, 999a8c51b3fSopenharmony_ci 'cpu_time': 90, 1000a8c51b3fSopenharmony_ci 'cpu_time_other': 89}, 1001a8c51b3fSopenharmony_ci {'time': -0.125, 'cpu': -0.16279069767441862, 'real_time': 8, 1002a8c51b3fSopenharmony_ci 'real_time_other': 7, 'cpu_time': 86, 'cpu_time_other': 72} 1003a8c51b3fSopenharmony_ci ], 1004a8c51b3fSopenharmony_ci 'time_unit': 'ns', 1005a8c51b3fSopenharmony_ci 'utest': { 1006a8c51b3fSopenharmony_ci 'have_optimal_repetitions': False, 'cpu_pvalue': 0.6666666666666666, 'time_pvalue': 1.0 1007a8c51b3fSopenharmony_ci } 1008a8c51b3fSopenharmony_ci }, 1009a8c51b3fSopenharmony_ci { 1010a8c51b3fSopenharmony_ci 'name': u'short', 1011a8c51b3fSopenharmony_ci 'measurements': [ 1012a8c51b3fSopenharmony_ci {'time': -0.125, 1013a8c51b3fSopenharmony_ci 'cpu': -0.0625, 1014a8c51b3fSopenharmony_ci 'real_time': 8, 1015a8c51b3fSopenharmony_ci 'real_time_other': 7, 1016a8c51b3fSopenharmony_ci 'cpu_time': 80, 1017a8c51b3fSopenharmony_ci 'cpu_time_other': 75}, 1018a8c51b3fSopenharmony_ci {'time': -0.4325, 1019a8c51b3fSopenharmony_ci 'cpu': -0.13506493506493514, 1020a8c51b3fSopenharmony_ci 'real_time': 8, 1021a8c51b3fSopenharmony_ci 'real_time_other': 4.54, 1022a8c51b3fSopenharmony_ci 'cpu_time': 77, 1023a8c51b3fSopenharmony_ci 'cpu_time_other': 66.6} 1024a8c51b3fSopenharmony_ci ], 1025a8c51b3fSopenharmony_ci 'time_unit': 'ns', 1026a8c51b3fSopenharmony_ci 'utest': { 1027a8c51b3fSopenharmony_ci 'have_optimal_repetitions': False, 'cpu_pvalue': 0.2, 'time_pvalue': 0.7670968684102772 1028a8c51b3fSopenharmony_ci } 1029a8c51b3fSopenharmony_ci }, 1030a8c51b3fSopenharmony_ci { 1031a8c51b3fSopenharmony_ci 'name': u'medium', 1032a8c51b3fSopenharmony_ci 'measurements': [ 1033a8c51b3fSopenharmony_ci {'real_time_other': 5, 1034a8c51b3fSopenharmony_ci 'cpu_time': 80, 1035a8c51b3fSopenharmony_ci 'time': -0.375, 1036a8c51b3fSopenharmony_ci 'real_time': 8, 1037a8c51b3fSopenharmony_ci 'cpu_time_other': 53, 1038a8c51b3fSopenharmony_ci 'cpu': -0.3375 1039a8c51b3fSopenharmony_ci } 1040a8c51b3fSopenharmony_ci ], 1041a8c51b3fSopenharmony_ci 'utest': {}, 1042a8c51b3fSopenharmony_ci 'time_unit': u'ns', 1043a8c51b3fSopenharmony_ci 'aggregate_name': '' 1044a8c51b3fSopenharmony_ci }, 1045a8c51b3fSopenharmony_ci { 1046a8c51b3fSopenharmony_ci 'name': 'OVERALL_GEOMEAN', 1047a8c51b3fSopenharmony_ci 'measurements': [{'real_time': 8.48528137423858e-09, 'cpu_time': 8.441336246629233e-08, 1048a8c51b3fSopenharmony_ci 'real_time_other': 2.2405267593145244e-08, 'cpu_time_other': 2.5453661413660466e-08, 1049a8c51b3fSopenharmony_ci 'time': 1.6404861082353634, 'cpu': -0.6984640740519662}], 1050a8c51b3fSopenharmony_ci 'time_unit': 's', 1051a8c51b3fSopenharmony_ci 'run_type': 'aggregate', 1052a8c51b3fSopenharmony_ci 'aggregate_name': 'geomean', 1053a8c51b3fSopenharmony_ci 'utest': {} 1054a8c51b3fSopenharmony_ci } 1055a8c51b3fSopenharmony_ci ] 1056a8c51b3fSopenharmony_ci self.assertEqual(len(self.json_diff_report), len(expected_output)) 1057a8c51b3fSopenharmony_ci for out, expected in zip( 1058a8c51b3fSopenharmony_ci self.json_diff_report, expected_output): 1059a8c51b3fSopenharmony_ci self.assertEqual(out['name'], expected['name']) 1060a8c51b3fSopenharmony_ci self.assertEqual(out['time_unit'], expected['time_unit']) 1061a8c51b3fSopenharmony_ci assert_utest(self, out, expected) 1062a8c51b3fSopenharmony_ci assert_measurements(self, out, expected) 1063a8c51b3fSopenharmony_ci 1064a8c51b3fSopenharmony_ci 1065a8c51b3fSopenharmony_ciclass TestReportDifferenceForPercentageAggregates( 1066a8c51b3fSopenharmony_ci unittest.TestCase): 1067a8c51b3fSopenharmony_ci @classmethod 1068a8c51b3fSopenharmony_ci def setUpClass(cls): 1069a8c51b3fSopenharmony_ci def load_results(): 1070a8c51b3fSopenharmony_ci import json 1071a8c51b3fSopenharmony_ci testInputs = os.path.join( 1072a8c51b3fSopenharmony_ci os.path.dirname( 1073a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 1074a8c51b3fSopenharmony_ci 'Inputs') 1075a8c51b3fSopenharmony_ci testOutput1 = os.path.join(testInputs, 'test4_run0.json') 1076a8c51b3fSopenharmony_ci testOutput2 = os.path.join(testInputs, 'test4_run1.json') 1077a8c51b3fSopenharmony_ci with open(testOutput1, 'r') as f: 1078a8c51b3fSopenharmony_ci json1 = json.load(f) 1079a8c51b3fSopenharmony_ci with open(testOutput2, 'r') as f: 1080a8c51b3fSopenharmony_ci json2 = json.load(f) 1081a8c51b3fSopenharmony_ci return json1, json2 1082a8c51b3fSopenharmony_ci 1083a8c51b3fSopenharmony_ci json1, json2 = load_results() 1084a8c51b3fSopenharmony_ci cls.json_diff_report = get_difference_report( 1085a8c51b3fSopenharmony_ci json1, json2, utest=True) 1086a8c51b3fSopenharmony_ci 1087a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing(self): 1088a8c51b3fSopenharmony_ci expect_lines = [ 1089a8c51b3fSopenharmony_ci ['whocares', '-0.5000', '+0.5000', '0', '0', '0', '0'] 1090a8c51b3fSopenharmony_ci ] 1091a8c51b3fSopenharmony_ci output_lines_with_header = print_difference_report( 1092a8c51b3fSopenharmony_ci self.json_diff_report, 1093a8c51b3fSopenharmony_ci utest=True, utest_alpha=0.05, use_color=False) 1094a8c51b3fSopenharmony_ci output_lines = output_lines_with_header[2:] 1095a8c51b3fSopenharmony_ci print("\n") 1096a8c51b3fSopenharmony_ci print("\n".join(output_lines_with_header)) 1097a8c51b3fSopenharmony_ci self.assertEqual(len(output_lines), len(expect_lines)) 1098a8c51b3fSopenharmony_ci for i in range(0, len(output_lines)): 1099a8c51b3fSopenharmony_ci parts = [x for x in output_lines[i].split(' ') if x] 1100a8c51b3fSopenharmony_ci self.assertEqual(expect_lines[i], parts) 1101a8c51b3fSopenharmony_ci 1102a8c51b3fSopenharmony_ci def test_json_diff_report(self): 1103a8c51b3fSopenharmony_ci expected_output = [ 1104a8c51b3fSopenharmony_ci { 1105a8c51b3fSopenharmony_ci 'name': u'whocares', 1106a8c51b3fSopenharmony_ci 'measurements': [ 1107a8c51b3fSopenharmony_ci {'time': -0.5, 1108a8c51b3fSopenharmony_ci 'cpu': 0.5, 1109a8c51b3fSopenharmony_ci 'real_time': 0.01, 1110a8c51b3fSopenharmony_ci 'real_time_other': 0.005, 1111a8c51b3fSopenharmony_ci 'cpu_time': 0.10, 1112a8c51b3fSopenharmony_ci 'cpu_time_other': 0.15} 1113a8c51b3fSopenharmony_ci ], 1114a8c51b3fSopenharmony_ci 'time_unit': 'ns', 1115a8c51b3fSopenharmony_ci 'utest': {} 1116a8c51b3fSopenharmony_ci } 1117a8c51b3fSopenharmony_ci ] 1118a8c51b3fSopenharmony_ci self.assertEqual(len(self.json_diff_report), len(expected_output)) 1119a8c51b3fSopenharmony_ci for out, expected in zip( 1120a8c51b3fSopenharmony_ci self.json_diff_report, expected_output): 1121a8c51b3fSopenharmony_ci self.assertEqual(out['name'], expected['name']) 1122a8c51b3fSopenharmony_ci self.assertEqual(out['time_unit'], expected['time_unit']) 1123a8c51b3fSopenharmony_ci assert_utest(self, out, expected) 1124a8c51b3fSopenharmony_ci assert_measurements(self, out, expected) 1125a8c51b3fSopenharmony_ci 1126a8c51b3fSopenharmony_ci 1127a8c51b3fSopenharmony_ciclass TestReportSorting(unittest.TestCase): 1128a8c51b3fSopenharmony_ci @classmethod 1129a8c51b3fSopenharmony_ci def setUpClass(cls): 1130a8c51b3fSopenharmony_ci def load_result(): 1131a8c51b3fSopenharmony_ci import json 1132a8c51b3fSopenharmony_ci testInputs = os.path.join( 1133a8c51b3fSopenharmony_ci os.path.dirname( 1134a8c51b3fSopenharmony_ci os.path.realpath(__file__)), 1135a8c51b3fSopenharmony_ci 'Inputs') 1136a8c51b3fSopenharmony_ci testOutput = os.path.join(testInputs, 'test4_run.json') 1137a8c51b3fSopenharmony_ci with open(testOutput, 'r') as f: 1138a8c51b3fSopenharmony_ci json = json.load(f) 1139a8c51b3fSopenharmony_ci return json 1140a8c51b3fSopenharmony_ci 1141a8c51b3fSopenharmony_ci cls.json = load_result() 1142a8c51b3fSopenharmony_ci 1143a8c51b3fSopenharmony_ci def test_json_diff_report_pretty_printing(self): 1144a8c51b3fSopenharmony_ci import util 1145a8c51b3fSopenharmony_ci 1146a8c51b3fSopenharmony_ci expected_names = [ 1147a8c51b3fSopenharmony_ci "99 family 0 instance 0 repetition 0", 1148a8c51b3fSopenharmony_ci "98 family 0 instance 0 repetition 1", 1149a8c51b3fSopenharmony_ci "97 family 0 instance 0 aggregate", 1150a8c51b3fSopenharmony_ci "96 family 0 instance 1 repetition 0", 1151a8c51b3fSopenharmony_ci "95 family 0 instance 1 repetition 1", 1152a8c51b3fSopenharmony_ci "94 family 0 instance 1 aggregate", 1153a8c51b3fSopenharmony_ci "93 family 1 instance 0 repetition 0", 1154a8c51b3fSopenharmony_ci "92 family 1 instance 0 repetition 1", 1155a8c51b3fSopenharmony_ci "91 family 1 instance 0 aggregate", 1156a8c51b3fSopenharmony_ci "90 family 1 instance 1 repetition 0", 1157a8c51b3fSopenharmony_ci "89 family 1 instance 1 repetition 1", 1158a8c51b3fSopenharmony_ci "88 family 1 instance 1 aggregate" 1159a8c51b3fSopenharmony_ci ] 1160a8c51b3fSopenharmony_ci 1161a8c51b3fSopenharmony_ci for n in range(len(self.json['benchmarks']) ** 2): 1162a8c51b3fSopenharmony_ci random.shuffle(self.json['benchmarks']) 1163a8c51b3fSopenharmony_ci sorted_benchmarks = util.sort_benchmark_results(self.json)[ 1164a8c51b3fSopenharmony_ci 'benchmarks'] 1165a8c51b3fSopenharmony_ci self.assertEqual(len(expected_names), len(sorted_benchmarks)) 1166a8c51b3fSopenharmony_ci for out, expected in zip(sorted_benchmarks, expected_names): 1167a8c51b3fSopenharmony_ci self.assertEqual(out['name'], expected) 1168a8c51b3fSopenharmony_ci 1169a8c51b3fSopenharmony_ci 1170a8c51b3fSopenharmony_cidef assert_utest(unittest_instance, lhs, rhs): 1171a8c51b3fSopenharmony_ci if lhs['utest']: 1172a8c51b3fSopenharmony_ci unittest_instance.assertAlmostEqual( 1173a8c51b3fSopenharmony_ci lhs['utest']['cpu_pvalue'], 1174a8c51b3fSopenharmony_ci rhs['utest']['cpu_pvalue']) 1175a8c51b3fSopenharmony_ci unittest_instance.assertAlmostEqual( 1176a8c51b3fSopenharmony_ci lhs['utest']['time_pvalue'], 1177a8c51b3fSopenharmony_ci rhs['utest']['time_pvalue']) 1178a8c51b3fSopenharmony_ci unittest_instance.assertEqual( 1179a8c51b3fSopenharmony_ci lhs['utest']['have_optimal_repetitions'], 1180a8c51b3fSopenharmony_ci rhs['utest']['have_optimal_repetitions']) 1181a8c51b3fSopenharmony_ci else: 1182a8c51b3fSopenharmony_ci # lhs is empty. assert if rhs is not. 1183a8c51b3fSopenharmony_ci unittest_instance.assertEqual(lhs['utest'], rhs['utest']) 1184a8c51b3fSopenharmony_ci 1185a8c51b3fSopenharmony_ci 1186a8c51b3fSopenharmony_cidef assert_measurements(unittest_instance, lhs, rhs): 1187a8c51b3fSopenharmony_ci for m1, m2 in zip(lhs['measurements'], rhs['measurements']): 1188a8c51b3fSopenharmony_ci unittest_instance.assertEqual(m1['real_time'], m2['real_time']) 1189a8c51b3fSopenharmony_ci unittest_instance.assertEqual(m1['cpu_time'], m2['cpu_time']) 1190a8c51b3fSopenharmony_ci # m1['time'] and m1['cpu'] hold values which are being calculated, 1191a8c51b3fSopenharmony_ci # and therefore we must use almost-equal pattern. 1192a8c51b3fSopenharmony_ci unittest_instance.assertAlmostEqual(m1['time'], m2['time'], places=4) 1193a8c51b3fSopenharmony_ci unittest_instance.assertAlmostEqual(m1['cpu'], m2['cpu'], places=4) 1194a8c51b3fSopenharmony_ci 1195a8c51b3fSopenharmony_ci 1196a8c51b3fSopenharmony_ciif __name__ == '__main__': 1197a8c51b3fSopenharmony_ci unittest.main() 1198a8c51b3fSopenharmony_ci 1199a8c51b3fSopenharmony_ci# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 1200a8c51b3fSopenharmony_ci# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off; 1201a8c51b3fSopenharmony_ci# kate: indent-mode python; remove-trailing-spaces modified; 1202