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