13af6ab5fSopenharmony_ci#!/usr/bin/env python3 23af6ab5fSopenharmony_ci# -*- coding: utf-8 -*- 33af6ab5fSopenharmony_ci 43af6ab5fSopenharmony_ci""" 53af6ab5fSopenharmony_ciCopyright (c) 2023 Huawei Device Co., Ltd. 63af6ab5fSopenharmony_ciLicensed under the Apache License, Version 2.0 (the "License"); 73af6ab5fSopenharmony_ciyou may not use this file except in compliance with the License. 83af6ab5fSopenharmony_ciYou may obtain a copy of the License at 93af6ab5fSopenharmony_ci 103af6ab5fSopenharmony_ci http://www.apache.org/licenses/LICENSE-2.0 113af6ab5fSopenharmony_ci 123af6ab5fSopenharmony_ciUnless required by applicable law or agreed to in writing, software 133af6ab5fSopenharmony_cidistributed under the License is distributed on an "AS IS" BASIS, 143af6ab5fSopenharmony_ciWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 153af6ab5fSopenharmony_ciSee the License for the specific language governing permissions and 163af6ab5fSopenharmony_cilimitations under the License. 173af6ab5fSopenharmony_ci""" 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_ciimport argparse 203af6ab5fSopenharmony_ciimport math 213af6ab5fSopenharmony_ciimport os 223af6ab5fSopenharmony_ciimport time 233af6ab5fSopenharmony_cifrom config import COMP, DEFAULT_RUNS, PARSE_ONLY, OPT_LEVEL, RUNS_NUM, DEFAULT_PARAMS, CUR_FILE_DIR, \ 243af6ab5fSopenharmony_ci DEFAULT_TESTCASES_DIR, SELECTED_PARAMETERS, JS_FILE_SUFFIX, TS_FILE_SUFFIX, REPORT_DIR, TEST_RESULT_FILE, \ 253af6ab5fSopenharmony_ci DEFAULT_OUTPUT_DIR, ABC_FILE_SUFFIX, DEFAULT_HERMES_PARAMS, DEFAULT_HERMES_PATH, HERMES_FILE_SUFFIX, \ 263af6ab5fSopenharmony_ci HERMES_CODE_PATH, ES2ABC, HERMES 273af6ab5fSopenharmony_cifrom utils import traverse_dir, write_result, write_html, run_cmd_cwd, clear_folder_shutil, pull_cases, remove_dir, \ 283af6ab5fSopenharmony_ci pull_build_hermes 293af6ab5fSopenharmony_ci 303af6ab5fSopenharmony_ci 313af6ab5fSopenharmony_cidef parse_args(): 323af6ab5fSopenharmony_ci parser = argparse.ArgumentParser() 333af6ab5fSopenharmony_ci parser.add_argument('--es2abc-tool', 343af6ab5fSopenharmony_ci required=True, 353af6ab5fSopenharmony_ci help="es2abc tool path") 363af6ab5fSopenharmony_ci parser.add_argument('--runs', required=False, type=int, 373af6ab5fSopenharmony_ci default=DEFAULT_RUNS, 383af6ab5fSopenharmony_ci help='Number of runs') 393af6ab5fSopenharmony_ci parser.add_argument('--opt-level', required=False, choices=['0', '1', '2'], 403af6ab5fSopenharmony_ci help="Specifies the compiler optimization level") 413af6ab5fSopenharmony_ci parser.add_argument('--parse-only', required=False, 423af6ab5fSopenharmony_ci default=False, action='store_true', 433af6ab5fSopenharmony_ci help="During the test, only the input file is parsed") 443af6ab5fSopenharmony_ci parser.add_argument('--engine-comp', required=False, 453af6ab5fSopenharmony_ci default=False, action='store_true', 463af6ab5fSopenharmony_ci help="Compared to the other engine") 473af6ab5fSopenharmony_ci arguments = parser.parse_args() 483af6ab5fSopenharmony_ci return arguments 493af6ab5fSopenharmony_ci 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ciclass Es2AbcBenchMarks: 523af6ab5fSopenharmony_ci def __init__(self, args): 533af6ab5fSopenharmony_ci self.args = args 543af6ab5fSopenharmony_ci self.results = [] 553af6ab5fSopenharmony_ci self.cmds = {} 563af6ab5fSopenharmony_ci self.select_params = [] 573af6ab5fSopenharmony_ci 583af6ab5fSopenharmony_ci def parse_args(self): 593af6ab5fSopenharmony_ci cmds = {ES2ABC: [self.args.es2abc_tool]} 603af6ab5fSopenharmony_ci if self.args.parse_only and not self.args.engine_comp: 613af6ab5fSopenharmony_ci cmds[ES2ABC].append('--parse-only') 623af6ab5fSopenharmony_ci self.select_params.append(f'{PARSE_ONLY}:True') 633af6ab5fSopenharmony_ci else: 643af6ab5fSopenharmony_ci self.select_params.append(f'{PARSE_ONLY}:False') 653af6ab5fSopenharmony_ci if self.args.opt_level and not self.args.engine_comp: 663af6ab5fSopenharmony_ci cmds[ES2ABC].append(f'--opt-level {self.args.opt_level}') 673af6ab5fSopenharmony_ci self.select_params.append(f'{OPT_LEVEL}:{self.args.opt_level}') 683af6ab5fSopenharmony_ci else: 693af6ab5fSopenharmony_ci self.select_params.append(f'{OPT_LEVEL}:0') 703af6ab5fSopenharmony_ci self.select_params.append(f'{RUNS_NUM}:{self.args.runs}') 713af6ab5fSopenharmony_ci cmds[ES2ABC] += DEFAULT_PARAMS 723af6ab5fSopenharmony_ci if self.args.engine_comp: 733af6ab5fSopenharmony_ci cmds[HERMES] = [DEFAULT_HERMES_PATH] + DEFAULT_HERMES_PARAMS 743af6ab5fSopenharmony_ci self.select_params.append(f'{COMP}:True') 753af6ab5fSopenharmony_ci else: 763af6ab5fSopenharmony_ci self.select_params.append(f'{COMP}:False') 773af6ab5fSopenharmony_ci self.cmds = cmds 783af6ab5fSopenharmony_ci 793af6ab5fSopenharmony_ci def run(self): 803af6ab5fSopenharmony_ci test_case_path = os.path.join(CUR_FILE_DIR, DEFAULT_TESTCASES_DIR) 813af6ab5fSopenharmony_ci test_cases_files = traverse_dir(test_case_path) 823af6ab5fSopenharmony_ci self.parse_args() 833af6ab5fSopenharmony_ci html_data = {} 843af6ab5fSopenharmony_ci selected_params = f'{SELECTED_PARAMETERS}: {"; ".join(self.select_params)}' 853af6ab5fSopenharmony_ci write_result(selected_params) 863af6ab5fSopenharmony_ci for dir_name, file_paths in test_cases_files.items(): 873af6ab5fSopenharmony_ci case_dir_name = os.path.basename(dir_name) 883af6ab5fSopenharmony_ci case_info_html_data = {} 893af6ab5fSopenharmony_ci case_info_path = os.path.join(REPORT_DIR, f'{case_dir_name}.html') 903af6ab5fSopenharmony_ci print(f"---------------------------{case_dir_name}--------------------------------") 913af6ab5fSopenharmony_ci for engine_type in self.cmds: 923af6ab5fSopenharmony_ci print(f">>>engine {engine_type}") 933af6ab5fSopenharmony_ci case_execution_time_sum, means = self.run_benchmark(file_paths, engine_type, case_dir_name, 943af6ab5fSopenharmony_ci case_info_html_data) 953af6ab5fSopenharmony_ci print(f">>>Done. \n") 963af6ab5fSopenharmony_ci case_execution_time_sum_avg = str(case_execution_time_sum) 973af6ab5fSopenharmony_ci score_sum = self.args.runs / self.gen_score(means) 983af6ab5fSopenharmony_ci test_result = [f'{case_dir_name}', case_execution_time_sum_avg, f'{score_sum * 100}'.split('.')[0], 993af6ab5fSopenharmony_ci case_info_path, self.args.runs] 1003af6ab5fSopenharmony_ci if engine_type in html_data: 1013af6ab5fSopenharmony_ci html_data[engine_type].append(test_result) 1023af6ab5fSopenharmony_ci else: 1033af6ab5fSopenharmony_ci html_data[engine_type] = [test_result] 1043af6ab5fSopenharmony_ci write_html(case_info_html_data, case_info_path, selected_params, info=True) 1053af6ab5fSopenharmony_ci print("-------------------------------------------------------------------\n") 1063af6ab5fSopenharmony_ci write_html(html_data, os.path.join(REPORT_DIR, TEST_RESULT_FILE), selected_params, info=False) 1073af6ab5fSopenharmony_ci 1083af6ab5fSopenharmony_ci def run_benchmark(self, file_paths, engine_type, case_dir_name, case_info_html_data): 1093af6ab5fSopenharmony_ci case_execution_time_sum = 0 1103af6ab5fSopenharmony_ci means = [] 1113af6ab5fSopenharmony_ci for file_path in file_paths: 1123af6ab5fSopenharmony_ci file_name = os.path.basename(file_path) 1133af6ab5fSopenharmony_ci if not (file_name.endswith(JS_FILE_SUFFIX) or file_name.endswith(TS_FILE_SUFFIX)): 1143af6ab5fSopenharmony_ci continue 1153af6ab5fSopenharmony_ci print(f'Running {file_name.replace(JS_FILE_SUFFIX, "").replace(TS_FILE_SUFFIX, "")} ') 1163af6ab5fSopenharmony_ci case_execution_time, case_execution_times = self.run_single_benchmark(file_path, engine_type) 1173af6ab5fSopenharmony_ci case_execution_time_ms = str(case_execution_time * 1000).split(".")[0] 1183af6ab5fSopenharmony_ci case_execution_time_sum += int(case_execution_time_ms) 1193af6ab5fSopenharmony_ci mean = self.gen_score(case_execution_times) 1203af6ab5fSopenharmony_ci means.append(mean) 1213af6ab5fSopenharmony_ci score = self.args.runs / mean 1223af6ab5fSopenharmony_ci score = f'{score * 100}'.split('.')[0] 1233af6ab5fSopenharmony_ci log_str = (f'engine {engine_type} case: {os.path.join(case_dir_name, file_name)} number of runs: ' 1243af6ab5fSopenharmony_ci f'{self.args.runs} avg time: {case_execution_time_ms}ms Score:{score}\n') 1253af6ab5fSopenharmony_ci single_case_result = [f'{os.path.join(case_dir_name, file_name)}', case_execution_time_ms, score, 1263af6ab5fSopenharmony_ci self.args.runs] 1273af6ab5fSopenharmony_ci if engine_type in case_info_html_data: 1283af6ab5fSopenharmony_ci case_info_html_data[engine_type].append(single_case_result) 1293af6ab5fSopenharmony_ci else: 1303af6ab5fSopenharmony_ci case_info_html_data[engine_type] = [single_case_result] 1313af6ab5fSopenharmony_ci write_result(log_str) 1323af6ab5fSopenharmony_ci return case_execution_time_sum, means 1333af6ab5fSopenharmony_ci 1343af6ab5fSopenharmony_ci def run_single_benchmark(self, file_path, engine_type): 1353af6ab5fSopenharmony_ci elapsed_sum = 0 1363af6ab5fSopenharmony_ci case_execution_times = [] 1373af6ab5fSopenharmony_ci new_cmds = [i for i in self.cmds[engine_type]] 1383af6ab5fSopenharmony_ci output_file = os.path.join(DEFAULT_OUTPUT_DIR, os.path.basename(file_path). 1393af6ab5fSopenharmony_ci replace(JS_FILE_SUFFIX, ABC_FILE_SUFFIX). 1403af6ab5fSopenharmony_ci replace(TS_FILE_SUFFIX, ABC_FILE_SUFFIX)) 1413af6ab5fSopenharmony_ci if engine_type == ES2ABC: 1423af6ab5fSopenharmony_ci new_cmds += [file_path, "--output", output_file] 1433af6ab5fSopenharmony_ci else: 1443af6ab5fSopenharmony_ci new_cmds += [output_file.replace(ABC_FILE_SUFFIX, HERMES_FILE_SUFFIX), file_path] 1453af6ab5fSopenharmony_ci for _ in range(self.args.runs): 1463af6ab5fSopenharmony_ci start = time.time() 1473af6ab5fSopenharmony_ci run_cmd_cwd(new_cmds) 1483af6ab5fSopenharmony_ci elapsed_sum += time.time() - start 1493af6ab5fSopenharmony_ci case_execution_times.append(elapsed_sum) 1503af6ab5fSopenharmony_ci return elapsed_sum / self.args.runs, case_execution_times 1513af6ab5fSopenharmony_ci 1523af6ab5fSopenharmony_ci @staticmethod 1533af6ab5fSopenharmony_ci def gen_score(numbers): 1543af6ab5fSopenharmony_ci log = 0 1553af6ab5fSopenharmony_ci for num in numbers: 1563af6ab5fSopenharmony_ci log += math.log(num) 1573af6ab5fSopenharmony_ci mean = math.exp(log / len(numbers)) 1583af6ab5fSopenharmony_ci return mean 1593af6ab5fSopenharmony_ci 1603af6ab5fSopenharmony_ci 1613af6ab5fSopenharmony_cidef prepare_and_run(args): 1623af6ab5fSopenharmony_ci clear_folder_shutil(DEFAULT_OUTPUT_DIR) 1633af6ab5fSopenharmony_ci clear_folder_shutil(REPORT_DIR) 1643af6ab5fSopenharmony_ci clear_folder_shutil(DEFAULT_TESTCASES_DIR) 1653af6ab5fSopenharmony_ci pull_cases_success = pull_cases() 1663af6ab5fSopenharmony_ci if pull_cases_success: 1673af6ab5fSopenharmony_ci abc_runner = Es2AbcBenchMarks(args) 1683af6ab5fSopenharmony_ci abc_runner.run() 1693af6ab5fSopenharmony_ci remove_dir(DEFAULT_OUTPUT_DIR) 1703af6ab5fSopenharmony_ci print("> > > Done.") 1713af6ab5fSopenharmony_ci 1723af6ab5fSopenharmony_ci 1733af6ab5fSopenharmony_cidef main(): 1743af6ab5fSopenharmony_ci args = parse_args() 1753af6ab5fSopenharmony_ci print("> > > benchmark running") 1763af6ab5fSopenharmony_ci if args.engine_comp: 1773af6ab5fSopenharmony_ci clear_folder_shutil(HERMES_CODE_PATH) 1783af6ab5fSopenharmony_ci print("Building Hermes...") 1793af6ab5fSopenharmony_ci build_result = pull_build_hermes() 1803af6ab5fSopenharmony_ci if not build_result: 1813af6ab5fSopenharmony_ci raise Exception('build hermes failed.') 1823af6ab5fSopenharmony_ci prepare_and_run(args) 1833af6ab5fSopenharmony_ci 1843af6ab5fSopenharmony_ci 1853af6ab5fSopenharmony_ciif __name__ == "__main__": 1863af6ab5fSopenharmony_ci main() 187