1#!/bin/bash 2# Copyright (c) 2023 Huawei Device Co., Ltd. 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15set -e 16 17declare -i ret_error=1 18declare SCRIPT_NAME 19SCRIPT_NAME="$(basename "$0")" 20declare JS_PERF_RESULT_PATH="" 21declare OPENHARMONY_ROOT_PATH="" 22declare D8_BINARY_PATH="/usr/bin/v8/d8" 23declare D8_DEVICE_DIR="" 24declare CONFIG_PATH 25CONFIG_PATH="$(dirname "${BASH_SOURCE[0]}")"/config.json 26declare VER_PLATFORM="full_x86_64" 27declare -a BENCH_FILTER=() 28declare -a EXCLUDE_BENCHMARKS=() 29declare NO_NEED_DOWNLOAD_BENCHS=false 30declare BENCH_MULTIPLIER="" 31declare HDC_PATH="" 32declare TASKSET_MASK="" 33declare -i ITERATIONS=1 34 35function echo_fatal() 36{ 37 echo "Error: $1" 38 exit 1 39} 40 41function init() 42{ 43 while [[ -n "$1" ]] 44 do 45 case $1 in 46 --help|-h) 47 usage 48 exit 0 49 ;; 50 --d8-host-path) 51 shift 52 D8_BINARY_PATH="$1" 53 ;; 54 --d8-device-dir) 55 shift 56 D8_DEVICE_DIR="$1" 57 ;; 58 --platform) 59 shift 60 VER_PLATFORM="$1" 61 ;; 62 --config) 63 shift 64 CONFIG_PATH="$1" 65 ;; 66 --bench-filter=*) 67 local BENCH_FILTER_STR="${1#*=}" 68 BENCH_FILTER=(${BENCH_FILTER_STR//:/ }) 69 ;; 70 --exclude=*) 71 local EXCLUDE_BENCHS_STR="${1#*=}" 72 EXCLUDE_BENCHMARKS=(${EXCLUDE_BENCHS_STR//:/ }) 73 ;; 74 --no-download-benchs) 75 NO_NEED_DOWNLOAD_BENCHS=true 76 ;; 77 --multiplier) 78 shift 79 BENCH_MULTIPLIER=$1 80 ;; 81 --iterations) 82 shift 83 ITERATIONS=$1 84 ;; 85 --hdc-path) 86 shift 87 HDC_PATH="$1" 88 ;; 89 --taskset) 90 shift 91 TASKSET_MASK="$1" 92 ;; 93 *) 94 JS_PERF_RESULT_PATH="$1" 95 OPENHARMONY_ROOT_PATH="$2" 96 break 97 ;; 98 esac 99 shift 100 done 101 if [[ "${VER_PLATFORM}" == *arm64* ]] 102 then 103 if [[ -z "${D8_DEVICE_DIR}" ]] 104 then 105 echo_fatal "--d8-device-dir is required for device" 106 fi 107 if [[ ! -d "${D8_DEVICE_DIR}" ]] 108 then 109 echo_fatal "${D8_DEVICE_DIR}: directory with v8 libs for device does not exist" 110 fi 111 if [[ ! -f "${D8_DEVICE_DIR}/d8" ]] 112 then 113 echo_fatal "${D8_DEVICE_DIR}/d8 is required, but does not exist" 114 fi 115 if [[ ! -f "${D8_DEVICE_DIR}/snapshot_blob.bin" ]] 116 then 117 echo_fatal "${D8_DEVICE_DIR}/snapshot_blob.bin is required, but does not exist" 118 fi 119 if [[ ! -f "${D8_DEVICE_DIR}/icudtl.dat" ]] 120 then 121 echo_fatal "${D8_DEVICE_DIR}/icudtl.dat is required, but does not exist" 122 fi 123 if [[ -z "${HDC_PATH}" ]] 124 then 125 if ! command -v hdc 126 then 127 echo_fatal "hdc path was not specified" 128 fi 129 HDC_PATH=$(command -v hdc) 130 elif [[ ! -e "${HDC_PATH}" ]] 131 then 132 echo_fatal "Executable file does not exist: ${HDC_PATH}" 133 else 134 HDC_PATH=$(realpath "${HDC_PATH}") 135 fi 136 elif [[ ! -x "${D8_BINARY_PATH}" ]] 137 then 138 echo_fatal "Executable file does not exist: ${D8_BINARY_PATH}" 139 fi 140 if [[ ! -f "${CONFIG_PATH}" ]] 141 then 142 echo_fatal "Config file does not exist: ${CONFIG_PATH}" 143 fi 144 CONFIG_PATH=$(realpath "${CONFIG_PATH}") 145 if [[ -z "${JS_PERF_RESULT_PATH}" ]] 146 then 147 usage 148 echo_fatal "JS_PERF_RESULT_PATH argument is not set" 149 fi 150 if [[ -z "${OPENHARMONY_ROOT_PATH}" ]] 151 then 152 usage 153 echo_fatal "OPENHARMONY_ROOT argument is not set" 154 fi 155 if [[ ! -d "${OPENHARMONY_ROOT_PATH}" ]] 156 then 157 echo_fatal "Path to openharmony root dir does not exist: ${OPENHARMONY_ROOT_PATH}" 158 else 159 OPENHARMONY_ROOT_PATH="$(realpath "${OPENHARMONY_ROOT_PATH}")" 160 fi 161 if [[ ! -d "${JS_PERF_RESULT_PATH}" ]] 162 then 163 mkdir -p "${JS_PERF_RESULT_PATH}" 164 fi 165 JS_PERF_RESULT_PATH="$(realpath "${JS_PERF_RESULT_PATH}")" 166 WORKDIR_PATH="${JS_PERF_RESULT_PATH}/workdir" 167 if [[ -d "${WORKDIR_PATH}" ]] 168 then 169 rm -rf "${WORKDIR_PATH}" 170 fi 171 mkdir -p "${WORKDIR_PATH}" 172 echo " 173OpenHarmony root path: ${OPENHARMONY_ROOT_PATH} 174JS perf results: ${JS_PERF_RESULT_PATH} 175Config: ${CONFIG_PATH} 176Platform: ${VER_PLATFORM} 177" 178} 179 180function check_command_exist() 181{ 182 command=$1 183 type "$command" >/dev/null 2>&1 184 echo $? 185} 186 187function check_pip_component() 188{ 189 pip3 list|grep "$1" 190 return $? 191} 192 193function prepare_js_test_files() 194{ 195 local -r bench_repo_path="${JS_PERF_RESULT_PATH}/code/arkjs-perf-test" 196 if ! ${NO_NEED_DOWNLOAD_BENCHS} 197 then 198 rm -rf "${bench_repo_path}" 199 fi 200 if [[ ! -d "${bench_repo_path}" ]] 201 then 202 mkdir -p "${bench_repo_path}" 203 git clone -b builtins_test1110 https://gitee.com/dov1s/arkjs-perf-test.git "${bench_repo_path}" 204 fi 205 local -r test_dir="js-perf-test" 206 JS_TEST_PATH="${JS_PERF_RESULT_PATH}/${test_dir}" 207 if [[ -d "${JS_TEST_PATH}" ]] 208 then 209 rm -rf "${JS_TEST_PATH}" 210 fi 211 mkdir -p "${JS_TEST_PATH}" 212 if [[ ${#BENCH_FILTER[@]} -eq 0 ]] 213 then 214 cp -r "${bench_repo_path}/${test_dir}"/* "${JS_TEST_PATH}" 215 else 216 for bench in "${BENCH_FILTER[@]}" 217 do 218 if [[ -d "${bench_repo_path}/${test_dir}/${bench}" ]] 219 then 220 mkdir -p "${JS_TEST_PATH}/${bench}" 221 cp -r "${bench_repo_path}/${test_dir}/${bench}"/* "${JS_TEST_PATH}/${bench}" 222 elif [[ -f "${bench_repo_path}/${test_dir}/${bench}" ]] 223 then 224 mkdir -p "$(dirname "${JS_TEST_PATH}/${bench}")" 225 cp "${bench_repo_path}/${test_dir}/${bench}" "${JS_TEST_PATH}/${bench}" 226 else 227 echo "No benchmarks for filter '${bench}'" 228 fi 229 done 230 fi 231 if [[ ${#EXCLUDE_BENCHMARKS[@]} -ne 0 ]] 232 then 233 for bench in "${EXCLUDE_BENCHMARKS[@]}" 234 do 235 if [[ -e "${JS_TEST_PATH}/${bench}" ]] 236 then 237 rm -rf "${JS_TEST_PATH}/${bench}" 238 else 239 echo "No excluding benchmark '${bench}'" 240 fi 241 done 242 fi 243} 244 245 246function get_cores { 247 local -i cores_count 248 local -i mask=$((16#$1)) 249 cores_count=$(${HDC_PATH} shell nproc --all) 250 for i in $(seq 0 $((cores_count - 1)) ) 251 do 252 if [[ $((mask & 1)) -ne 0 ]] 253 then 254 cores+=("${i}") 255 fi 256 mask=$((mask >> 1)) 257 done 258} 259 260function fix_cores_freq() 261{ 262 if [[ -z "${TASKSET_MASK}" ]] 263 then 264 echo "Taskset mask was not set. Frequency for cores will not be fixed" 265 return 266 fi 267 local -a cores=() 268 get_cores "${TASKSET_MASK}" 269 echo "Using cores: ${cores[*]}" 270 declare -i avg_freq 271 declare freqs_str="" 272 declare -a freqs_arr=() 273 declare -i freq_index=0 274 for core in "${cores[@]}" 275 do 276 freqs_str=$(hdc shell "cat /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_available_frequencies") 277 # split string to array 278 freqs_arr=(${freqs_str}) 279 freq_index=$(( ${#freqs_arr[@]} / 2 )) 280 avg_freq=${freqs_arr[${freq_index}]} 281 ${HDC_PATH} shell "echo performance > /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_governor" 282 ${HDC_PATH} shell "echo ${avg_freq} > /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_min_freq" 283 ${HDC_PATH} shell "echo ${avg_freq} > /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_max_freq" 284 done 285 echo "Cores info after frequencies fix:" 286 for core in "${cores[@]}" 287 do 288 echo "Core ${core} info:" 289 echo "Governor: $(${HDC_PATH} shell "cat /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_governor")" 290 echo "Min freq: $(${HDC_PATH} shell "cat /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_min_freq")" 291 echo "Max freq: $(${HDC_PATH} shell "cat /sys/devices/system/cpu/cpu${core}/cpufreq/scaling_max_freq")" 292 done 293} 294 295function prepare_device() 296{ 297 # Check device 298 local -a devices 299 devices=$(${HDC_PATH} list targets) 300 if [[ ${#devices[@]} -eq 1 ]] 301 then 302 if [[ "${devices[0]}" == "[Empty]"* ]] 303 then 304 echo_fatal "No devices" 305 fi 306 echo "Device id: ${devices[0]}" 307 else 308 echo_fatal "Required immidieatly one device" 309 fi 310 # Create workdir 311 local -r WORKDIR_ON_DEVICE="/data/local/tmp/jsperftest" 312 D8_BINARY_PATH="${WORKDIR_ON_DEVICE}/v8/d8" 313 set -x 314 ${HDC_PATH} shell "rm -rf ${WORKDIR_ON_DEVICE}" 315 ${HDC_PATH} shell "mkdir -p ${WORKDIR_ON_DEVICE}/v8 ${WORKDIR_ON_DEVICE}/lib ${WORKDIR_ON_DEVICE}/thirdparty" 316 ${HDC_PATH} file send "${D8_DEVICE_DIR}"/d8 ${D8_BINARY_PATH} 317 ${HDC_PATH} shell chmod u+x "${D8_BINARY_PATH}" 318 ${HDC_PATH} file send "${D8_DEVICE_DIR}"/snapshot_blob.bin ${WORKDIR_ON_DEVICE}/v8 319 ${HDC_PATH} file send "${D8_DEVICE_DIR}"/icudtl.dat ${WORKDIR_ON_DEVICE}/v8 320 set +x 321 fix_cores_freq 322} 323 324function usage() 325{ 326 echo "${SCRIPT_NAME} [options] <JS_PERF_RESULT_PATH> <OPENHARMONY_ROOT> 327Options: 328 --d8-host-path <path> - path to d8 binary file. 329 Default: /usr/bin/v8/d8 330 --d8-device-dir <path> - path to dir with d8 for ohos device. 331 See https://gitee.com/qishui7/ohcompiler-daily/repository/archive/master.zip 332 --hdc-path <hdc_path> - path to hdc executable file. Use from PATH env variable by default 333 --platform <platform> - used platform. Possible values in config.json. 334 Default: full_x86_64 335 --config <config_path> - path to specific json config 336 --taskset mask - use CPU affinity with mask for benchmark runnings. 337 Frequency of these cores will be fixed 338 --multiplier N - iteration multiplier for js benchmarks 339 --iterations N - number of benchmark launches and get average 340 --bench-filter=BenchDir1:BenchDir2:BenchDir3/bench.js:... 341 - filter for benchmarks: directory or file 342 --exclude=BenchDir1:BenchDir2:BenchDir3/bench.js:... 343 - exclude benchmarks from running: directory or file 344 --no-download-benchs - no download benchmarks from repository if repo already exists 345 --help, -h - print help info about script 346 347Positional arguments: 348 JS_PERF_RESULT_PATH - directory path to benchmark results 349 OPENHARMONY_ROOT - path to root directory for ark_js_vm and es2panda 350" 351} 352 353main() 354{ 355 init "$@" 356 cur_path=$(dirname "$(readlink -f "$0")") 357 358 check_command_exist git || { echo "git is not available"; return $ret_error; } 359 check_command_exist unzip || { echo "unzip is not available"; return $ret_error; } 360 check_command_exist jq || { echo "jq is not available"; return $ret_error; } 361 check_command_exist python3 || { echo "python3 is not available"; return $ret_error; } 362 check_pip_component "openpyxl" || { pip3 install openpyxl; } 363 364 [ -f "$cur_path/run_js_test.py" ] || { echo "no run_js_test.py, please check it";return $ret_error;} 365 366 if [[ "${VER_PLATFORM}" == *arm64* ]] 367 then 368 prepare_device 369 fi 370 371 prepare_js_test_files || { return $ret_error; } 372 373 cd "${WORKDIR_PATH}" 374 if [[ -n "${BENCH_MULTIPLIER}" ]] 375 then 376 for js_test in $(find ${JS_TEST_PATH} -name "*js") 377 do 378 python3 "${cur_path}"/prerun_proc.py __MULTIPLIER__="${BENCH_MULTIPLIER}" "${js_test}" 379 done 380 fi 381 mkdir -p "${WORKDIR_PATH}/tmp" 382 echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" 383 local -i benchs_time_start benchs_time benchs_minutes 384 benchs_time_start=$(date +%s) 385 python3 "${cur_path}"/run_js_test.py \ 386 -c "${CONFIG_PATH}" \ 387 -bp "${OPENHARMONY_ROOT_PATH}" \ 388 -p "${JS_TEST_PATH}" \ 389 -o "${JS_PERF_RESULT_PATH}" \ 390 -v "${D8_BINARY_PATH}" \ 391 -e "${VER_PLATFORM}" \ 392 --hdc "${HDC_PATH}" \ 393 -t "${TASKSET_MASK}" \ 394 -n "${ITERATIONS}" 395 benchs_time=$(($(date +%s) - benchs_time_start)) 396 benchs_minutes=$((benchs_time / 60)) 397 echo "Benchmark script time: ${benchs_minutes} min $((benchs_time - benchs_minutes * 60)) sec" 398 399 if [[ "${VER_PLATFORM}" == *arm64* && -n "${TASKSET_MASK}" ]] 400 then 401 echo "Reboot device after fix frequencies for restoring of default values" 402 ${HDC_PATH} shell reboot 403 fi 404} 405 406main "$@" 407exit $? 408