1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2023 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15#/ 16 17import argparse 18import re 19 20 21class BenchmarkDataParser: 22 def __init__(self): 23 self.benchmark_data_before = {} 24 self.benchmark_data_after = {} 25 self.all_cases = [] 26 27 @staticmethod 28 def get_format(before_data, after_data, pct, fluctuation_range): 29 deg_format = "\033[1;31m|{:60}|{:20}|{:20}|{:20}\033[0m|" 30 opt_format = "\033[1;32m|{:60}|{:20}|{:20}|{:20}\033[0m|" 31 equal_format = "\033[1;37m|{:60}|{:20}|{:20}|{:20}\033[0m|" 32 if pct <= fluctuation_range: 33 return equal_format 34 if before_data > after_data: 35 return opt_format 36 else: 37 return deg_format 38 39 @staticmethod 40 def print_header(args): 41 header_format = "\033[1;37m|{:60}|{:20}|{:20}|{:20}|\033[0m" 42 print("\033[1;34m[Notice]:\033[0m") 43 print("file before optimization: " + args.before) 44 print("file after optimization: " + args.after) 45 print("allowed fluctuation range: " + args.range + "%") 46 print("\033[1;32mgreen is better, \033[0m" + 47 "\033[1;31mred is worse, \033[0m" + 48 "\033[1;37mwhite is equal.\033[0m") 49 print("\033[1;34m[Compare Result]:\033[0m") 50 print(header_format.format("case", "before(ns)", "after(ns)", "(before - after / before)")) 51 print(header_format.format("----", "----", "----", "----")) 52 53 def read_file(self, file_path, is_before): 54 bench_pattern = re.compile(r''' 55 ^([\S]+) # case name 56 [^0-9]+ 57 ([0-9,.]+) # time 58 [^0-9]+ 59 ([0-9|.]+) # cpu 60 [^0-9]+ 61 ([0-9|.]+) # iters 62 .*''', re.VERBOSE) 63 64 if is_before: 65 current_data = self.benchmark_data_before 66 else: 67 current_data = self.benchmark_data_after 68 69 lines = open(file_path, 'r').readlines() 70 for line in lines: 71 if line.lower().startswith("bm_"): 72 m = bench_pattern.match(line) 73 if m: 74 case, time, cpu, iters = m.groups() 75 self.all_cases.append(case) if self.all_cases.count(case) == 0 else self.all_cases 76 current_data[case] = [float(time), float(cpu), float(iters)] 77 else: 78 print("match error: {}".format(line)) 79 80 def out_results(self, args): 81 self.print_header(args) 82 for case in self.all_cases: 83 before_data = self.benchmark_data_before[case][0] if case in self.benchmark_data_before.keys() else 0 84 after_data = self.benchmark_data_after[case][0] if case in self.benchmark_data_after.keys() else 0 85 pct = 0 if before_data == 0 else round((abs(before_data - after_data) / before_data) * 100, 2) 86 sign = "+" if (before_data - after_data) > 0 else "-" 87 output_format = self.get_format(before_data, after_data, pct, float(args.range)) 88 signed_pct = "{}{}{}".format(sign, str(pct), "%") 89 print(output_format.format(str(case), str(before_data), str(after_data), signed_pct)) 90 91 92def main(): 93 parser = argparse.ArgumentParser() 94 parser.add_argument('-b', '--before', type=str, help='file before optimization') 95 parser.add_argument('-a', '--after', type=str, help='file after optimization') 96 parser.add_argument('-r', '--range', type=str, help='allowed fluctuation range') 97 98 args = parser.parse_args() 99 100 benchmark_data_parser = BenchmarkDataParser() 101 benchmark_data_parser.read_file(args.before, 1) 102 benchmark_data_parser.read_file(args.after, 0) 103 benchmark_data_parser.out_results(args) 104 105 106if __name__ == '__main__': 107 main()