107 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			107 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | #!/usr/bin/env python | ||
|  | # -*- coding: utf-8 -*- | ||
|  | # Copyright (c) 2023 Huawei Device Co., Ltd. | ||
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
|  | # you may not use this file except in compliance with the License. | ||
|  | # You may obtain a copy of the License at | ||
|  | # | ||
|  | #     http://www.apache.org/licenses/LICENSE-2.0 | ||
|  | # | ||
|  | # Unless required by applicable law or agreed to in writing, software | ||
|  | # distributed under the License is distributed on an "AS IS" BASIS, | ||
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|  | # See the License for the specific language governing permissions and | ||
|  | # limitations under the License. | ||
|  | #/ | ||
|  | 
 | ||
|  | import argparse | ||
|  | import re | ||
|  | 
 | ||
|  | 
 | ||
|  | class BenchmarkDataParser: | ||
|  |     def __init__(self): | ||
|  |         self.benchmark_data_before = {} | ||
|  |         self.benchmark_data_after = {} | ||
|  |         self.all_cases = [] | ||
|  | 
 | ||
|  |     @staticmethod | ||
|  |     def get_format(before_data, after_data, pct, fluctuation_range): | ||
|  |         deg_format = "\033[1;31m|{:60}|{:20}|{:20}|{:20}\033[0m|" | ||
|  |         opt_format = "\033[1;32m|{:60}|{:20}|{:20}|{:20}\033[0m|" | ||
|  |         equal_format = "\033[1;37m|{:60}|{:20}|{:20}|{:20}\033[0m|" | ||
|  |         if pct <= fluctuation_range: | ||
|  |             return equal_format | ||
|  |         if before_data > after_data: | ||
|  |             return opt_format | ||
|  |         else: | ||
|  |             return deg_format | ||
|  | 
 | ||
|  |     @staticmethod | ||
|  |     def print_header(args): | ||
|  |         header_format = "\033[1;37m|{:60}|{:20}|{:20}|{:20}|\033[0m" | ||
|  |         print("\033[1;34m[Notice]:\033[0m") | ||
|  |         print("file before optimization: " + args.before) | ||
|  |         print("file after optimization: " + args.after) | ||
|  |         print("allowed fluctuation range: " + args.range + "%") | ||
|  |         print("\033[1;32mgreen is better, \033[0m" + | ||
|  |               "\033[1;31mred is worse, \033[0m" + | ||
|  |               "\033[1;37mwhite is equal.\033[0m") | ||
|  |         print("\033[1;34m[Compare Result]:\033[0m") | ||
|  |         print(header_format.format("case", "before(ns)", "after(ns)", "(before - after / before)")) | ||
|  |         print(header_format.format("----", "----", "----", "----")) | ||
|  | 
 | ||
|  |     def read_file(self, file_path, is_before): | ||
|  |         bench_pattern = re.compile(r'''
 | ||
|  |             ^([\S]+)   # case name | ||
|  |             [^0-9]+ | ||
|  |             ([0-9,.]+) # time | ||
|  |             [^0-9]+ | ||
|  |             ([0-9|.]+) # cpu | ||
|  |             [^0-9]+ | ||
|  |             ([0-9|.]+) # iters | ||
|  |             .*''', re.VERBOSE)
 | ||
|  | 
 | ||
|  |         if is_before: | ||
|  |             current_data = self.benchmark_data_before | ||
|  |         else: | ||
|  |             current_data = self.benchmark_data_after | ||
|  | 
 | ||
|  |         lines = open(file_path, 'r').readlines() | ||
|  |         for line in lines: | ||
|  |             if line.lower().startswith("bm_"): | ||
|  |                 m = bench_pattern.match(line) | ||
|  |                 if m: | ||
|  |                     case, time, cpu, iters = m.groups() | ||
|  |                     self.all_cases.append(case) if self.all_cases.count(case) == 0 else self.all_cases | ||
|  |                     current_data[case] = [float(time), float(cpu), float(iters)] | ||
|  |                 else: | ||
|  |                     print("match error: {}".format(line)) | ||
|  | 
 | ||
|  |     def out_results(self, args): | ||
|  |         self.print_header(args) | ||
|  |         for case in self.all_cases: | ||
|  |             before_data = self.benchmark_data_before[case][0] if case in self.benchmark_data_before.keys() else 0 | ||
|  |             after_data = self.benchmark_data_after[case][0] if case in self.benchmark_data_after.keys() else 0 | ||
|  |             pct = 0 if before_data == 0 else round((abs(before_data - after_data) / before_data) * 100, 2) | ||
|  |             sign = "+" if (before_data - after_data) > 0  else "-" | ||
|  |             output_format = self.get_format(before_data, after_data, pct, float(args.range)) | ||
|  |             signed_pct = "{}{}{}".format(sign, str(pct), "%") | ||
|  |             print(output_format.format(str(case), str(before_data), str(after_data), signed_pct)) | ||
|  | 
 | ||
|  | 
 | ||
|  | def main(): | ||
|  |     parser = argparse.ArgumentParser() | ||
|  |     parser.add_argument('-b', '--before', type=str, help='file before optimization') | ||
|  |     parser.add_argument('-a', '--after', type=str, help='file after optimization') | ||
|  |     parser.add_argument('-r', '--range', type=str, help='allowed fluctuation range') | ||
|  | 
 | ||
|  |     args = parser.parse_args() | ||
|  | 
 | ||
|  |     benchmark_data_parser = BenchmarkDataParser() | ||
|  |     benchmark_data_parser.read_file(args.before,  1) | ||
|  |     benchmark_data_parser.read_file(args.after, 0) | ||
|  |     benchmark_data_parser.out_results(args) | ||
|  | 
 | ||
|  | 
 | ||
|  | if __name__ == '__main__': | ||
|  |     main() |