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))