aboutsummaryrefslogtreecommitdiff
path: root/utils/utils_benchmarks.sh
blob: c8899c3ce46f4ddcbdcbb39fde4e4ed50e6a2dba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#!/bin/bash
#
# Copyright (c) 2020, Linaro Ltd.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

if [[ ! -v JCPU_COUNT ]]; then
  log E "utils_android.sh must be sourced before utils_benchmarks.sh"
  abort
fi

# Return the path to the boot image.
get_boot_image_path() {
  echo "/apex/com.android.art/javalib/boot.art"
}

# Return the name of the file which for the provided benchmark name.
# Args:
#   $1: the benchmark name.
get_benchmark_file_name() {
  local benchmark=$1
  local -r workspace="$(get_workspace)"
  echo "${workspace}/benchmarks/${benchmark}.java"
}

# Build benchmarks.
# $@: Names of benchmarks to build. The empty list causes all benchmarks to be built.
build_benchmarks() {
  local benchmark_files=()
  local bench
  for bench in "$@"; do
    benchmark_files+=("$(get_benchmark_file_name "${bench}")")
  done
  safe ./benchmarks/build.sh -t "${benchmark_files[@]}"
}

# Get the core bootclasspath which can be used to build and to run Java apps on a target.
get_target_core_bootclasspath() {
  # Get a list of bootjars names. They are space separated.
  local -r core_bootjars_names=$("$(get_art_tools_dir)"/bootjars.sh --core --target)

  # Get a space separated list of all bootjars names with names of apex modules they belong to.
  # They have the format: <apex module name>:<bootjar name>
  local boot_jars_names_with_apex_module=$("$(get_art_tools_dir)"/bootjars.sh --target)

  # Add '.jar' to core bootjars.
  # 'boot_jars_names_with_apex_module' will become like
  # 'com.android.art:apache-xml.jar platform:framework-minus-apex'.
  local name
  for name in ${core_bootjars_names}; do
    boot_jars_names_with_apex_module="${boot_jars_names_with_apex_module//${name}/${name}.jar}"
  done

  local bootclasspath=""
  for name in ${boot_jars_names_with_apex_module}; do
    if [[ "${name}" == *jar ]]; then
      # Convert the name into a file path: /apex/<module>/javalib/<jar>.
      name="/apex/${name//://javalib/}"
      bootclasspath="${bootclasspath}${name}:"
    fi
  done

  # SPECjvm2008 crypto workloads depend on conscrypt.jar.
  # 'conscrypt.jar' is separated from the core boot jars into a separate module.
  local -r conscrypt_jar="/apex/com.android.conscrypt/javalib/conscrypt.jar"

  echo "${bootclasspath}${conscrypt_jar}"
}

# Get target bootclasspath options for dex2oat which are used in ART testing.
get_target_art_test_bootclasspath_for_dex2oat() {
  local -r bootclasspath=$(get_target_core_bootclasspath)
  local -r boot_image="$(get_boot_image_path)"

  echo "--boot-image=${boot_image} \
        --runtime-arg -Xbootclasspath-locations:${bootclasspath} \
        --runtime-arg -Xbootclasspath:${bootclasspath}"
}

# Get target dex2oat command.
# Args:
#  $1: ISA specification, e.g. arm64.
#  $2: APK file.
#  $3: ISA features, e.g. runtime. (optional)
get_target_dex2oat_cmd() {
  local -r isa=$1
  local -r apk_file=$2
  local -r isa_features=${3:-default}
  local -r oat_dir="$(dirname "${apk_file}")/oat/${isa}"
  local -r apk_name="$(basename "${apk_file}" .apk)"

  echo "/system/bin/dex2oat -g --compact-dex-level=none \
        --resolve-startup-const-strings=true \
        --instruction-set=${isa} \
        --runtime-arg -Xnorelocate \
        --dex-file=${apk_file} \
        --oat-file=${oat_dir}/${apk_name}.odex \
        --app-image-file=${oat_dir}/${apk_name}.art \
        --instruction-set-features=${isa_features}"
}

# Assert that the cpu option is valid.
# Args:
#  $1: the cpu option.
validate_cpu_option() {
  local -r cpu="$1"

  if [[ "${cpu}" != @(all|big|little|default) ]]; then
    log E "Invalid CPU option: ${cpu}"
    exit 1
  fi
}

# Assert that the mode option is valid.
# Args:
#  $1: the mode option.
validate_mode_option() {
  local -r mode="$1"

  if [[ "${mode}" != @(all|32|64) ]]; then
    log E "Invalid mode option: ${mode}"
    exit 1
  fi
}

# Check that the specified benchmark names are valid.
# A benchmark name is valid if the java file 'benchmarks/<benchmark name>.java' exists.
# Args:
#  $@: benchmark names.
validate_benchmarks_names() {
  local -r workspace="$(get_workspace)"
  local benchmark
  for benchmark in "$@"; do
    local benchmark_java_file="$(get_benchmark_file_name "${benchmark}")"
    if [[ ! -f "${benchmark_java_file}" ]]; then
      log E "Java file ${benchmark_java_file} does not exist for benchmark ${benchmark}"
      exit 1
    fi
  done
}

# Get a dalvikvm command which can be used to run  Java apps on a target.
# Args:
#  $1: the working directory used for java.io.tmpdir.
#  $2: the classpath (it can be empty).
get_target_dalvikvm_cmd() {
  local -r work_dir=$1
  local -r classpath=$2

  local classpath_arg=""
  if [[ -n "${classpath}" ]]; then
    classpath_arg="-cp ${classpath}"
  fi

  echo "/system/bin/dalvikvm -Xusejit:false \
        -Djava.io.tmpdir=${work_dir} \
        ${classpath_arg}"
}

# Get a dalvikvm command which is used in ART testing.
# Args:
#  $1: the working directory used for java.io.tmpdir.
#  $2: the classpath (it can be empty).
#  $3: ISA features, e.g. runtime. (optional)
get_target_art_test_dalvikvm_cmd() {
  local -r work_dir=$1
  local -r classpath_arg=$2
  local -r isa_features=${3:-default}
  local -r target_bootclasspath=$(get_target_core_bootclasspath)
  local -r boot_image="$(get_boot_image_path)"
  local -r additional_cmd_args="-Ximage:${boot_image} \
                                -Xbootclasspath-locations:${target_bootclasspath} \
                                -Xbootclasspath:${target_bootclasspath} \
                                -Xcompiler-option \
                                  --instruction-set-features=${isa_features}"

  echo "$(get_target_dalvikvm_cmd "${work_dir}" "${classpath_arg}") \
        ${additional_cmd_args}"
}

# Get exports of environment variables which are used in ART testing.
get_target_art_test_env_vars_exports() {
  local exports=""

  ### Form the content of the 'exports' variable. ###
  read -r -d '' exports << EOM
export ANDROID_ROOT=/system
export ANDROID_DATA=/data/local/tmp/
export ANDROID_ART_ROOT=${ART_TEST_APEX_ART_ROOT}
export ANDROID_TZDATA_ROOT=${ART_TEST_APEX_TZDATA_ROOT}
export ANDROID_I18N_ROOT=${ART_TEST_APEX_I18N_ROOT}
EOM
  ### End of the content of the 'exports' variable. ###

  echo "${exports}"
}

# Get CPU affinity mask.
# Args:
#  $@: CPU numbers, e.g. 0 1 2 3.
get_cpu_affinity_mask() {
  local int_mask=0
  local cpu
  for cpu in "$@"; do
    local cpu_bit=$((1 << cpu))
    int_mask=$((int_mask | cpu_bit))
  done
  printf "%x" "${int_mask}"
}

# Get the name of the directory used for runs.
get_target_virtual_work_dir() {
  echo "/data/local/tmp"
}

# In the chroot mode, commands for runs use virtual directories.
# The function returns the actual physical directory corresponding to the virtual
# directory. The physical directory is a directory relative to ART_TEST_CHROOT.
# Args:
#  $1: a virtual directory.
get_target_physical_dir() {
  echo "${ART_TEST_CHROOT}/$1"
}

# Require a target device to support big.LITTLE.
# If big.LITTLE is supported, it is checked that
# BIG_CPUS and LITTLE_CPUS are defined.
# Args:
#  $1: a target device
require_big_little_device() {
  local -r target_device="$1"
  if ! ${DEVICE_IS_BIG_LITTLE}; then
    log E "${target_device} is not big.LITTLE device."
    exit 1
  fi
  if [[ ! -v BIG_CPUS ]]; then
    log E "BIG_CPUS is not defined for ${target_device}."
    exit 1
  fi
  if [[ ! -v LITTLE_CPUS ]]; then
    log E "LITTLE_CPUS is not defined for ${target_device}."
    exit 1
  fi
}

# Get the path to the simpleperf directory.
get_simpleperf_home() {
  echo "$(get_workspace)/system/extras/simpleperf"
}

# Arguments:
#   ${1} - path to devices config
list_devices_from_config() {
  log I "--- List of supported devices in devices/config ---"
  local f
  for f in $1; do
    local filename=${f##*/}
    safe source "$f"
    log I "${filename%.*}: $DEVICE_NAME"
  done
}

# Reads
set_environment_for_benchmark_run() {
  local -n bench_options=$1
  set_environment_target
  if ${bench_options["linux"]}; then
    set_environment_linux_target
  fi
  if ${bench_options["sudo"]}; then
    set_environment_use_sudo
  fi
  if ${bench_options["x86"]}; then
    select_android_target "x86" ""
  else
    local target_device="${bench_options["target-device"]}"

    # When we actually are to run benchmark on the device and the target device is not specified try
    # to autodetect it.
    if [[ "${bench_options["skip-run"]}" == "false" && "${target_device}" == "" ]]; then
      log I "Retrieve the target device using adb getprop..."
      # Skip building adb on CI bots: they run inside a container where adb is
      # already sourced, and the full Android tree is not available.
      if [[ ! -v SOURCE_BUILD_URL ]]; then
        prepare_adb
      fi
      target_device="$(retrieve_target_product_name)"
      log I "Target device to be used: ${target_device}."
    fi

    select_android_target "arm" "${target_device}"
  fi
  source_android_environment_default
}