1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4""" 5Copyright (c) 2023 Huawei Device Co., Ltd. 6Licensed under the Apache License, Version 2.0 (the "License"); 7you may not use this file except in compliance with the License. 8You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12Unless required by applicable law or agreed to in writing, software 13distributed under the License is distributed on an "AS IS" BASIS, 14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15See the License for the specific language governing permissions and 16limitations under the License. 17 18Description: Use ark to execute workload test suite 19""" 20 21import argparse 22import os 23import subprocess 24import platform 25import errno 26import sys 27import importlib 28import glob 29import datetime 30import stat 31from openpyxl import load_workbook, Workbook 32from openpyxl.styles import PatternFill 33 34 35class WorkLoadConfig: 36 TEST_WORKLOAD_GIT_URL = 'https://gitee.com/xliu-huanwei/ark-workload.git' 37 TEST_WORKLOAD_GIT_HASH = '90236fa3aa853db7af56d80cc6391432a51a1601' 38 START_INDEX = -19 39 END_INDEX = -5 40 41 42def str_to_bool(value): 43 if isinstance(value, bool): 44 return value 45 if value.lower() in ('true', '1'): 46 return True 47 elif value.lower() in ('false', '0'): 48 return False 49 else: 50 raise argparse.ArgumentTypeError('Invalid boolean value: {}'.format(value)) 51 52 53def parse_args(): 54 parser = argparse.ArgumentParser() 55 parser.add_argument('--code-path', metavar='DIR', 56 help='code root path') 57 parser.add_argument('--run-aot', default=False, nargs='?', type=str_to_bool, 58 help='Default Run run_pgo.sh, run-aot is true run run_aot.sh') 59 parser.add_argument('--report', default=False, nargs='?', type=str_to_bool, 60 help='Support daily care performance results and script ' 61 'preliminary analysis of performance data.') 62 parser.add_argument('--tools-type', default='dev', nargs='?', help='tools type') 63 parser.add_argument('--boundary-value', default=-10, nargs='?', 64 help='inferior boundary value') 65 parser.add_argument('--run-count', default='10', nargs='?', 66 help='Compile all cases, execute the case count') 67 return parser.parse_args() 68 69 70def execute_shell_command(command: str): 71 process = subprocess.Popen(command, shell=False) 72 process.wait() 73 74 75def execute_shell_command_add(command: list): 76 for file in glob.glob(command[-1]): 77 command[-1] = file 78 process = subprocess.Popen(command, shell=False) 79 process.wait() 80 81 82def git_clone(repository_url: str, destination_path: str): 83 command = ['git', 'clone', repository_url, destination_path] 84 if platform.system() == "Windows": 85 subprocess.run(command, check=True, shell=False) 86 else: 87 subprocess.run(command, check=True) 88 89 90def git_checkout(commit_hash: str, destination_path: str): 91 command = ['git', 'checkout', commit_hash] 92 subprocess.run(command, cwd=destination_path) 93 94 95def git_pull(check_out_dir=os.getcwd()): 96 cmds = ['git', 'pull', '--rebase'] 97 with subprocess.Popen(cmds, cwd=check_out_dir) as proc: 98 proc.wait() 99 100 101def git_clean(clean_dir=os.getcwd()): 102 cmds = ['git', 'checkout', '--', '.'] 103 with subprocess.Popen(cmds, cwd=clean_dir) as proc: 104 proc.wait() 105 106 107def execute_shell_script(script_path, args): 108 command = ['sh', script_path] + args 109 process = subprocess.Popen(command, stdout=subprocess.PIPE, 110 stderr=subprocess.PIPE, universal_newlines=True) 111 while True: 112 try: 113 text_data = process.stdout.readline() 114 sys.stdout.flush() 115 if len(text_data.strip()) != 0: 116 print(text_data.strip()) 117 except OSError as error: 118 if error == errno.ENOENT: 119 print("no such file") 120 elif error == errno.EPERM: 121 print("permission denied") 122 break 123 if not text_data: 124 break 125 process.wait() 126 return_code = process.returncode 127 if return_code != 0: 128 error_output = process.stderr.read().strip() 129 if error_output: 130 print(error_output) 131 132 133def configure_environment(path, file_path, tools_type): 134 text = "--case-path ts-swift-workload\n" \ 135 f"--ts-tools-path {path}\n" \ 136 f"--tools-type {tools_type}\n" \ 137 "--swift-tools-path ~/tools/swift-5.7.3-RELEASE-ubuntu22.04/usr/bin\n" \ 138 "--android-ndk ~/apple/android-ndk-r25c\n" \ 139 "--Ninja-ReleaseAssert ~/apple/build/Ninja-ReleaseAssert\n" \ 140 "end" 141 args = os.O_RDWR | os.O_CREAT 142 file_descriptor = os.open(file_path, args, stat.S_IRUSR | stat.S_IWUSR) 143 file_object = os.fdopen(file_descriptor, "w+") 144 file_object.write(text) 145 146 147def write_to_txt(file_path, text): 148 args = os.O_RDWR | os.O_CREAT | os.O_APPEND 149 file_descriptor = os.open(file_path, args, stat.S_IRUSR | stat.S_IWUSR) 150 file_object = os.fdopen(file_descriptor, "w+") 151 file_object.write(text) 152 153 154def prepare_workload_code(path): 155 data_dir = os.path.join("arkcompiler/ets_runtime/test/workloadtest/", "data") 156 if path: 157 data_dir = os.path.join(path, data_dir) 158 if not os.path.isdir(os.path.join(data_dir, '.git')): 159 git_clone(WorkLoadConfig.TEST_WORKLOAD_GIT_URL, data_dir) 160 os.chdir(data_dir) 161 git_checkout(WorkLoadConfig.TEST_WORKLOAD_GIT_HASH, './') 162 else: 163 os.chdir(data_dir) 164 git_clean(data_dir) 165 git_pull(data_dir) 166 git_checkout(WorkLoadConfig.TEST_WORKLOAD_GIT_HASH, './') 167 execute_shell_command_add(['chmod', '+x', '*.sh']) 168 execute_shell_command_add(['chmod', '+x', '*.py']) 169 try: 170 importlib.import_module('openpyxl') 171 except ImportError: 172 execute_shell_command(['pip', 'install', 'openpyxl']) 173 174 175def report(boundary_value: int): 176 del_out_file() 177 folder_path = "./" 178 file_pattern = "pgo_data_*.xlsx" 179 file_paths = glob.glob(os.path.join(folder_path, file_pattern)) 180 red_fill = PatternFill(start_color='FF0000', end_color='FF0000', fill_type='solid') 181 file_paths.sort(key=lambda x: datetime.datetime.strptime( 182 x[WorkLoadConfig.START_INDEX:WorkLoadConfig.END_INDEX], 183 "%Y%m%d%H%M%S"), reverse=True) 184 max_two_files = file_paths[:2] 185 if len(max_two_files) == 2: 186 wb_one = load_workbook(max_two_files[0]) 187 sheet_one = wb_one.active 188 wb_two = load_workbook(max_two_files[1]) 189 sheet_two = wb_two.active 190 data_one = [] 191 data_two = [] 192 for row in sheet_one.iter_rows(min_row=2, values_only=True): 193 data_one.append(row) 194 for row in sheet_two.iter_rows(min_row=2, values_only=True): 195 data_two.append(row) 196 if len(data_one) != len(data_two): 197 return 198 print('generate report dependent files:', max_two_files) 199 result_data = [] 200 write_to_txt('../out/pgo_daily.txt', 'case:percentage\n') 201 for row_one, row_two in zip(data_one, data_two): 202 case = row_one[0] 203 average_one = row_one[-1] 204 average_two = row_two[-1] 205 difference = (average_one - average_two) / average_one * 100 206 percentage = "{:.2f}%".format(difference) 207 result_data.append([case, percentage]) 208 write_to_txt('../out/pgo_daily.txt', case + percentage + '\n') 209 result_wb = Workbook() 210 result_sheet = result_wb.active 211 result_sheet.append(['case', 'percentage']) 212 for row in result_data: 213 result_sheet.append(row) 214 cell = result_sheet.cell(row=result_sheet.max_row, column=2) 215 if cell.value and float(cell.value.strip('%')) < boundary_value: 216 cell.fill = red_fill 217 now = datetime.datetime.now() 218 formatted_date = now.strftime("%Y%m%d%H%M%S") 219 daily_excel_name = "pgo_daily_" + formatted_date + ".xlsx" 220 daily_excel_out = "../out/pgo_daily.xlsx" 221 result_wb.save(daily_excel_name) 222 result_wb.save(daily_excel_out) 223 224 225def del_out_file(): 226 destination_dir = '../out/' 227 os.makedirs(destination_dir, exist_ok=True) 228 file_list = os.listdir(destination_dir) 229 for file_name in file_list: 230 file_path = os.path.join(destination_dir, file_name) 231 if os.path.isfile(file_path): 232 os.remove(file_path) 233 234 235def main(args): 236 print("\nWait a moment..........\n") 237 start_time = datetime.datetime.now() 238 prepare_workload_code(args.code_path) 239 tools_type = 'dev' 240 if args.tools_type: 241 tools_type = args.tools_type 242 boundary_value = -10 243 if args.boundary_value: 244 boundary_value = args.boundary_value 245 run_count = '10' 246 if args.run_count: 247 run_count = args.run_count 248 if args.run_aot: 249 print('execute run_aot.sh is currently not supported') 250 else: 251 configure_environment(args.code_path, 'toolspath.txt', tools_type) 252 execute_args = ['--build', '--excel', '--run-count'] 253 execute_args.append(run_count) 254 execute_shell_script("run_pgo.sh", execute_args) 255 end_time = datetime.datetime.now() 256 print(f"used time is: {str(end_time - start_time)}") 257 if args.report: 258 try: 259 report(int(args.boundary_value)) 260 except ValueError: 261 print('args.boundary_value value should be a number') 262 263 264if __name__ == "__main__": 265 sys.exit(main(parse_args())) 266