• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()