• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#
4# Copyright (c) 2023 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import os
18import stat
19import time
20import zipfile
21
22import numpy as np
23import pandas as pd
24
25import performance_build
26import performance_config
27
28from pylab import mpl
29
30
31class MailHelper():
32    def __init__(self):
33        mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei']
34        self.pic_table = {}
35        self.head_line = []
36        self.mail_msg = ''
37        self.logs_file = {}
38        self.failed_prjs = ''
39        self.data_count_in_line_graph = 10
40        MailHelper.remove_files()
41
42    @staticmethod
43    def remove_files():
44        if os.path.exists(performance_config.MailPicConfig.html_file_path):
45            os.remove(performance_config.MailPicConfig.html_file_path)
46        if os.path.exists(performance_config.MailPicConfig.attach_path):
47            os.remove(performance_config.MailPicConfig.attach_path)
48        if not os.path.exists(performance_config.MailPicConfig.mail_data_path):
49            os.mkdir(performance_config.MailPicConfig.mail_data_path)
50        for build_mode in range(2):
51                for log_type in range(3):
52                    pic_path = MailHelper.find_in_double_map(build_mode,
53                                                             log_type,
54                                                             performance_config.MailPicConfig.mail_pic_name,
55                                                             "mail_pic_name")
56                    if not pic_path:
57                        return
58                    if os.path.exists(pic_path):
59                        os.remove(pic_path)
60
61    @staticmethod
62    def find_in_double_map(key_1, key_2, double_dic, error_table_name):
63        it_1 = double_dic.get(key_1)
64        if it_1:
65            it_2 = it_1.get(key_2)
66            if not it_2:
67                print(f"Can not find key_2: {key_2} in {error_table_name}, please check")
68            return it_2
69        else:
70            print(f"Can not find key_1: {key_1} in {error_table_name}, please check")
71            return it_1
72
73    def add_msg(self, msg):
74        self.mail_msg += msg
75
76    def add_failed_project(self, prj_name, build_mode, log_type):
77        info = '-'.join((prj_name, build_mode, log_type)) + '<br>'
78        if self.failed_prjs == '':
79            self.failed_prjs = 'failed projects:<br>'
80        self.failed_prjs += info
81
82    def add_logs_file(self, filename, buffer):
83        self.logs_file[filename] = buffer
84
85    def add_pic_data(self, prj_name, is_debug, data_list):
86        build_mode = performance_config.BuildMode.DEBUG if is_debug else performance_config.BuildMode.RELEASE
87        it_1 = self.pic_table.get(prj_name)
88        prj_table = None
89        if it_1:
90            prj_table = it_1.get(build_mode)
91            if not prj_table:
92                it_1[build_mode] = [np.nan, np.nan, np.nan]
93        else:
94            self.pic_table[prj_name] = {build_mode:[np.nan, np.nan, np.nan]}
95            self.head_line.append(prj_name)
96            self.time_index = [time.strftime("%Y/%m/%d", time.localtime())]
97
98        prj_table = self.pic_table[prj_name][build_mode]
99        if len(data_list) == 1: # size
100            prj_table[2] = data_list[0]
101        else: # time
102            prj_table[0] = data_list[0]
103            prj_table[1] = data_list[1]
104
105    def create_msg_file(self):
106        with os.fdopen(
107            os.open(performance_config.MailPicConfig.html_file_path,
108                    os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
109                    stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG),
110                    'w', encoding='utf-8'
111            ) as msg_file:
112            if self.failed_prjs == '':
113                self.failed_prjs = 'All Build Succeed<br>'
114            self.mail_msg = performance_config.get_html_prefix().format(self.failed_prjs) + \
115                            self.mail_msg + \
116                            performance_config.get_html_suffix()
117            msg_file.write(self.mail_msg)
118
119    def create_logs_file(self):
120        mail_zip = zipfile.ZipFile(performance_config.MailPicConfig.attach_path, 'w')
121        for file in self.logs_file:
122            mail_zip.writestr(file, self.logs_file.get(file))
123        mail_zip.close()
124
125    @staticmethod
126    def draw_pic(df, pic_name, title_name, y_label):
127        ax = df.plot(
128                    linestyle='-',
129                    linewidth=2,
130                    marker='o',
131                    markersize=6,
132                    markeredgecolor='black',
133                    title=title_name,
134                    ylabel=y_label,
135                    grid=True,
136                    rot=30
137        )
138        i = 0
139        y_min, y_max = ax.get_ylim()
140        y_range = y_max - y_min
141        for idx, data in df.iterrows():
142            for k in data:
143                if not pd.isna(k):
144                    pos_y = k + y_range / 50 if i % 2 == 0 else k - y_range / 15
145                    ax.text(i - 0.1, pos_y, k)
146            i += 1
147        ax.get_figure().savefig(pic_name, bbox_inches='tight')
148
149    def create_pic(self):
150        for build_mode in range(2):
151            for log_type in range(3):
152                title_name = MailHelper.find_in_double_map(build_mode,
153                                                           log_type,
154                                                           performance_config.MailPicConfig.mail_pic_table_label,
155                                                           "mail_pic_table_label")
156                if not title_name:
157                    continue
158                pic_name = MailHelper.find_in_double_map(build_mode,
159                                                         log_type,
160                                                         performance_config.MailPicConfig.mail_pic_name,
161                                                         "mail_pic_name")
162                if not pic_name:
163                    continue
164                df = None
165                csv_filename = MailHelper.find_in_double_map(build_mode,
166                                                             log_type,
167                                                             performance_config.MailPicConfig.mail_pic_table_name,
168                                                             "pic_table_name")
169                if not csv_filename:
170                    continue
171                if os.path.exists(csv_filename):
172                    df = pd.read_csv(csv_filename, index_col=0)
173                else:
174                    df = pd.DataFrame(columns=self.head_line)
175                dic = {}
176                for prj_name in self.pic_table:
177                    dic[prj_name] = [self.pic_table[prj_name][build_mode][log_type]]
178                if len(dic) > 0:
179                    df_inserted = pd.DataFrame(dic, index=self.time_index)
180                    df = df._append(df_inserted)
181                df_length = len(df)
182                if df_length > self.data_count_in_line_graph:
183                    df = df[(df_length - self.data_count_in_line_graph) : df_length]
184                df.to_csv(csv_filename)
185                y_label = 'build time (s)' if log_type < performance_config.LogType.SIZE else 'size (Byte)'
186                self.draw_pic(df, pic_name, title_name, y_label)
187
188    def create_mail_files(self):
189        self.create_msg_file()
190        self.create_pic()
191        self.create_logs_file()
192
193
194class PerformanceEntry():
195    def __init__(self) -> None:
196        self.mail_helper = MailHelper()
197
198    def run(self):
199        self.init()
200        # You can control which project you need to test here, the first param is the key in performance_config.py
201        projects = performance_config.Config.run_list
202        for prj in projects:
203            self.start_test(prj)
204        self.create_mail_files()
205
206    def start_test(self, index):
207        config = performance_config.get_config(index)
208        if not config:
209            return
210        performance_build.run(config, self.mail_helper)
211
212    def create_mail_files(self):
213        if performance_config.Config.send_mail:
214            self.mail_helper.create_mail_files()
215
216    def init(self):
217        self.mail_helper = MailHelper()
218
219
220if __name__ == '__main__':
221    strat_time = time.time()
222    PerformanceEntry().run()
223    print("All test finished at %s\ntotal cost: %ds"
224          % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), time.time() - strat_time))