Add a linker relocation benchmark
The benchmark creates a set of DSOs that mimic the work involved in
loading the current version of libandroid_servers.so. The synthetic
benchmark has roughly the same number of libraries with roughly the same
relocations.
Currently, on a local aosp_walleye build that includes recent performance
improvements (including the Neon-based CL
I3983bca1dddc9241bb70290ad3651d895f046660), using the "performance"
governor, the benchmark reports these scores:
$ adb shell taskset 10 \
/data/benchmarktest64/linker-reloc-bench/linker-reloc-bench \
--benchmark_repetitions=20 --benchmark_display_aggregates_only=true
...
--------------------------------------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------------------------------------
BM_linker_relocation/real_time_mean 70048 us 465 us 20
BM_linker_relocation/real_time_median 70091 us 466 us 20
BM_linker_relocation/real_time_stddev 329 us 8.29 us 20
$ adb shell taskset 10 \
/data/benchmarktest/linker-reloc-bench/linker-reloc-bench \
--benchmark_repetitions=20 --benchmark_display_aggregates_only=true
...
--------------------------------------------------------------------------------
Benchmark Time CPU Iterations
--------------------------------------------------------------------------------
BM_linker_relocation/real_time_mean 83051 us 462 us 20
BM_linker_relocation/real_time_median 83069 us 464 us 20
BM_linker_relocation/real_time_stddev 184 us 8.91 us 20
Test: manual
Bug: none
Change-Id: I6dac66978f8666f95c76387093bda6be0151bfce
diff --git a/benchmarks/linker_relocation/run_bench_with_ninja.sh b/benchmarks/linker_relocation/run_bench_with_ninja.sh
new file mode 100755
index 0000000..8b39ffc
--- /dev/null
+++ b/benchmarks/linker_relocation/run_bench_with_ninja.sh
@@ -0,0 +1,154 @@
+#!/bin/bash -e
+#
+# Copyright (C) 2019 The Android Open Source Project
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+top=$(cd $(dirname $0) && pwd)
+
+usage() {
+cat <<EOF
+Usage: $0 [options]
+
+Toolchain:
+ --cc CC C compiler driver to compiler the benchmark with
+
+Run config:
+ --cpu-mask MASK MASK is a hex mask of CPU affinity passed to taskset
+ --linker LINKER Run the benchmark using a specific dynamic linker
+ --adb Run the test using adb
+
+Timing options:
+ --multitime N Use multitime to run the benchmark N iterations
+ --time CMD Use the given time command
+
+Misc:
+ --keep-tmp-dir Don't delete the temporary directory on exit
+
+Examples:
+ --cc "\$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang
+ -fuse-ld=lld -Wl,--pack-dyn-relocs=android+relr -Wl,--use-android-relr-tags"
+EOF
+ exit 0
+}
+
+cc=
+cpu_mask=0
+linker=
+use_adb=0
+time_cmd=
+keep_tmp_dir=0
+
+need_arg() {
+ if [ $2 -eq 0 ]; then
+ echo "error: $1 needs an argument"
+ exit 1
+ fi
+}
+
+while [ $# -gt 0 ]; do
+ arg=$1
+ shift
+ case "$arg" in
+ --cc) need_arg "$arg" "$#"; cc=$1; shift;;
+ --cpu-mask) need_arg "$arg" "$#"; cpu_mask=$1; shift;;
+ --linker) need_arg "#arg" "$#"; linker=$1; shift;;
+ --adb) use_adb=1;;
+ --multitime) need_arg "$arg" "$#"; time_cmd=--multitime=$1; shift;;
+ --time) need_arg "$arg" "$#"; time_cmd=--time=$1; shift;;
+ --keep-tmp-dir) keep_tmp_dir=1;;
+ --help) usage;;
+ *)
+ echo "error: unrecognized option: $arg"
+ exit 1
+ ;;
+ esac
+done
+
+# If no --cc is specified, use gcc because that's likely available.
+if [ "$cc" == "" ]; then
+ cc='gcc -ldl -pthread'
+fi
+
+case "$time_cmd" in
+ "") time_cmd=time;;
+ --time=*) time_cmd="${time_cmd#--time=}";;
+ --multitime=*)
+ iter="${time_cmd#--multitime=}"
+ if [ $use_adb -eq 1 ]; then
+ time_cmd="/data/local/tmp/multitime"
+ else
+ time_cmd="multitime"
+ fi
+ time_cmd="$time_cmd -n$iter -s0"
+ ;;
+esac
+
+# Generate the JSON file as a side effect of regenerating the benchmark.
+json_file=$top/tmp/libandroid_servers_arm64.json
+if [ ! -e $json_file ]; then
+ $top/gen_bench.sh --keep-tmp-dir --skip-gen-bench
+fi
+
+tmp_dir=$(mktemp -d)
+work_dir=$tmp_dir/linker-reloc-bench
+
+python3 -B $top/regen/gen_bench.py --ninja --cc "$cc" $json_file $work_dir
+
+env_setup=()
+if [ $use_adb -eq 1 ]; then
+ target_dir=/data/local/tmp/linker-reloc-bench
+ adb shell rm -rf $target_dir
+ (cd $tmp_dir; tar -c linker-reloc-bench/linker_reloc_bench_main linker-reloc-bench/*.so \
+ | gzip -1 -c | adb shell 'cd /data/local/tmp && tar xz')
+ env_setup+=( adb shell LD_LIBRARY_PATH=$target_dir )
+else
+ target_dir=$work_dir
+ env_setup+=( env LD_LIBRARY_PATH=$target_dir )
+fi
+
+main_cmd=()
+if [ "$linker" != "" ]; then
+ main_cmd+=( $linker )
+fi
+main_cmd+=( $target_dir/linker_reloc_bench_main )
+
+# Run the program once to warm the cache.
+echo "+ ${env_setup[@]}" "${main_cmd[@]}"
+ "${env_setup[@]}" "${main_cmd[@]}"
+
+# Run the benchmark proper.
+run_cmd=()
+if [ $cpu_mask -ne 0 ]; then
+ run_cmd+=( taskset $cpu_mask )
+fi
+run_cmd+=( $time_cmd )
+
+echo "+ ${env_setup[@]}" "${run_cmd[@]}" "${main_cmd[@]}"
+ "${env_setup[@]}" "${run_cmd[@]}" "${main_cmd[@]}"
+
+if [ $keep_tmp_dir -eq 0 ]; then
+ rm -fr $tmp_dir
+fi