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 28 29class MailHelper(): 30 def __init__(self): 31 self.pic_table = {} 32 self.head_line = [] 33 self.mail_msg = '' 34 self.logs_file = {} 35 self.failed_prjs = '' 36 MailHelper.remove_files() 37 38 @staticmethod 39 def remove_files(): 40 if os.path.exists(performance_config.MailPicConfig.html_file_path): 41 os.remove(performance_config.MailPicConfig.html_file_path) 42 if os.path.exists(performance_config.MailPicConfig.attach_path): 43 os.remove(performance_config.MailPicConfig.attach_path) 44 if not os.path.exists(performance_config.MailPicConfig.mail_data_path): 45 os.mkdir(performance_config.MailPicConfig.mail_data_path) 46 for build_mode in range(2): 47 for log_type in range(3): 48 pic_path = MailHelper.find_in_double_map(build_mode, 49 log_type, 50 performance_config.MailPicConfig.mail_pic_name, 51 "mail_pic_name") 52 if not pic_path: 53 return 54 if os.path.exists(pic_path): 55 os.remove(pic_path) 56 57 @staticmethod 58 def get_project_name(prj_name, aot_mode): 59 if aot_mode == performance_config.AotMode.NoAOT: 60 return prj_name 61 else: 62 return prj_name + ":aot:type" 63 64 def create(self, prj_name): 65 self.create_table(MailHelper.get_project_name(prj_name, performance_config.AotMode.Type)) 66 self.create_table(prj_name) 67 68 def create_table(self, prj_name): 69 self.pic_table[prj_name] = { 70 # full_time, incremental_time, size 71 performance_config.BuildMode.DEBUG:[np.nan, np.nan, np.nan], 72 performance_config.BuildMode.RELEASE:[np.nan, np.nan, np.nan] 73 } 74 self.head_line.append(prj_name) 75 self.time_index = [time.strftime("%Y/%m/%d", time.localtime())] 76 77 @staticmethod 78 def find_in_double_map(key_1, key_2, double_dic, error_table_name): 79 it_1 = double_dic.get(key_1) 80 if it_1: 81 it_2 = it_1.get(key_2) 82 if not it_2: 83 print(f"Can not find key_2: {key_2} in {error_table_name}, please check") 84 return it_2 85 else: 86 print(f"Can not find key_1: {key_1} in {error_table_name}, please check") 87 return it_1 88 89 def add_msg(self, msg): 90 self.mail_msg += msg 91 92 def add_failed_project(self, prj_name, build_mode, log_type, aot_type): 93 build_mode_info = 'Debug' if build_mode == performance_config.BuildMode.DEBUG else 'Release' 94 build_type_info = 'full_build' if log_type == performance_config.LogType.FULL else 'incremental_build' 95 aot_info = 'no_aot' if aot_type == performance_config.AotMode.NoAOT else 'aot_type' 96 info = '-'.join((prj_name, build_mode_info, build_type_info, aot_info)) + '<br>' 97 if self.failed_prjs == '': 98 self.failed_prjs = 'failed projects:<br>' 99 self.failed_prjs += info 100 101 def add_logs_file(self, filename, buffer): 102 self.logs_file[filename] = buffer 103 104 def add_pic_data(self, prj_name, is_debug, data_list): 105 build_mode = performance_config.BuildMode.DEBUG if is_debug else performance_config.BuildMode.RELEASE 106 prj_table = self.find_in_double_map(prj_name, build_mode, self.pic_table, "pic_table") 107 if prj_table: 108 if len(data_list) == 1: # size 109 prj_table[2] = data_list[0] 110 else: # time 111 prj_table[0] = data_list[0] 112 prj_table[1] = data_list[1] 113 114 def create_msg_file(self): 115 with os.fdopen( 116 os.open(performance_config.MailPicConfig.html_file_path, 117 os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 118 stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG), 119 'w' 120 ) as msg_file: 121 if self.failed_prjs == '': 122 self.failed_prjs = 'All Build Succeed<br>' 123 self.mail_msg = performance_config.get_html_prefix().format(self.failed_prjs) + \ 124 self.mail_msg + \ 125 performance_config.get_html_suffix() 126 msg_file.write(self.mail_msg) 127 128 def create_logs_file(self): 129 mail_zip = zipfile.ZipFile(performance_config.MailPicConfig.attach_path, 'w') 130 for file in self.logs_file: 131 mail_zip.writestr(file, self.logs_file.get(file)) 132 mail_zip.close() 133 134 @staticmethod 135 def draw_pic(df, pic_name, title_name, y_lable): 136 ax = df.plot( 137 linestyle='-', 138 linewidth=2, 139 marker='o', 140 markersize=6, 141 markeredgecolor='black', 142 title=title_name, 143 ylabel=y_lable, 144 grid=True 145 ) 146 i = 0 147 for idx, data in df.iterrows(): 148 for k in data: 149 if not pd.isna(k): 150 ax.text(i + 0.05, k + 0.1, k) 151 i += 1 152 ax.get_figure().savefig(pic_name) 153 154 def create_pic(self): 155 for build_mode in range(2): 156 for log_type in range(3): 157 title_name = MailHelper.find_in_double_map(build_mode, 158 log_type, 159 performance_config.MailPicConfig.mail_pic_table_lable, 160 "mail_pic_table_lable") 161 if not title_name: 162 continue 163 pic_name = MailHelper.find_in_double_map(build_mode, 164 log_type, 165 performance_config.MailPicConfig.mail_pic_name, 166 "mail_pic_name") 167 if not pic_name: 168 continue 169 df = None 170 csv_filename = MailHelper.find_in_double_map(build_mode, 171 log_type, 172 performance_config.MailPicConfig.mail_pic_table_name, 173 "pic_table_name") 174 if not csv_filename: 175 continue 176 if os.path.exists(csv_filename): 177 df = pd.read_csv(csv_filename, index_col=0) 178 else: 179 df = pd.DataFrame(columns=self.head_line) 180 dic = {} 181 for prj_name in self.pic_table: 182 dic[prj_name] = [self.pic_table[prj_name][build_mode][log_type]] 183 df_inserted = pd.DataFrame(dic, index=self.time_index) 184 df = df._append(df_inserted) 185 if len(df) > 5: 186 df = df[1:len(df)] 187 df.to_csv(csv_filename) 188 y_lable = 'build time (s)' if log_type < performance_config.LogType.SIZE else 'size (Byte)' 189 self.draw_pic(df, pic_name, title_name, y_lable) 190 191 def create_mail_files(self): 192 self.create_msg_file() 193 self.create_pic() 194 self.create_logs_file() 195 196 197class PerformanceEntry(): 198 def __init__(self) -> None: 199 self.mail_helper = MailHelper() 200 201 def run(self): 202 self.init() 203 # You can control which project you need to test here, the first param is the key in performance_config.py 204 projects = performance_config.Config.run_list 205 for prj in projects: 206 self.start_test(prj) 207 os.chdir(os.path.dirname(__file__)) 208 self.create_mail_files() 209 210 def start_test(self, index): 211 config = performance_config.get_config(index) 212 if not config: 213 return 214 self.mail_helper.create(os.path.basename(config.project_path)) 215 performance_build.run(config, self.mail_helper) 216 217 def create_mail_files(self): 218 if performance_config.Config.send_mail: 219 self.mail_helper.create_mail_files() 220 221 def init(self): 222 self.mail_helper = MailHelper() 223 224 225if __name__ == '__main__': 226 strat_time = time.time() 227 PerformanceEntry().run() 228 print("All test finished at %s\ntotal cost: %ds" 229 % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), time.time() - strat_time))