#!/bin/bash if [[ $# -le 1 ]]; then echo "Usage: $0 [] REFS..." exit 1 fi target="$1" shift addresses="" if [[ -e "$1" ]]; then addresses="$1" shift fi # path to "us" # readlink -f, but more portable: dirname=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$(dirname "$0")") # https://stackoverflow.com/a/2358432/472927 { # compile all refs pushd "$dirname" > /dev/null # if the user has some local changes, preserve them nstashed=$(git stash list | wc -l) echo "==> Stashing any local modifications" git stash --keep-index > /dev/null popstash() { # https://stackoverflow.com/q/24520791/472927 if [[ "$(git stash list | wc -l)" -ne "$nstashed" ]]; then echo "==> Restoring stashed state" git stash pop > /dev/null fi } # if the user has added stuff to the index, abort if ! git diff-index --quiet HEAD --; then echo "Refusing to overwrite outstanding git changes" popstash exit 2 fi current=$(git symbolic-ref --short HEAD) for ref in "$@"; do echo "==> Compiling $ref" git checkout -q "$ref" commit=$(git rev-parse HEAD) fn="target/release/addr2line-$commit" if [[ ! -e "$fn" ]]; then cargo build --release --example addr2line cp target/release/examples/addr2line "$fn" fi if [[ "$ref" != "$commit" ]]; then ln -sfn "addr2line-$commit" target/release/addr2line-"$ref" fi done git checkout -q "$current" popstash popd > /dev/null # get us some addresses to look up if [[ -z "$addresses" ]]; then echo "==> Looking for benchmarking addresses (this may take a while)" addresses=$(mktemp tmp.XXXXXXXXXX) objdump -C -x --disassemble -l "$target" \ | grep -P '0[048]:' \ | awk '{print $1}' \ | sed 's/:$//' \ > "$addresses" echo " -> Addresses stored in $addresses; you should re-use it next time" fi run() { func="$1" name="$2" cmd="$3" args="$4" printf "%s\t%s\t" "$name" "$func" if [[ "$cmd" =~ llvm-symbolizer ]]; then /usr/bin/time -f '%e\t%M' "$cmd" $args -obj="$target" < "$addresses" 2>&1 >/dev/null else /usr/bin/time -f '%e\t%M' "$cmd" $args -e "$target" < "$addresses" 2>&1 >/dev/null fi } # run without functions log1=$(mktemp tmp.XXXXXXXXXX) echo "==> Benchmarking" run nofunc binutils addr2line >> "$log1" #run nofunc elfutils eu-addr2line >> "$log1" run nofunc llvm-sym llvm-symbolizer -functions=none >> "$log1" for ref in "$@"; do run nofunc "$ref" "$dirname/target/release/addr2line-$ref" >> "$log1" done cat "$log1" | column -t # run with functions log2=$(mktemp tmp.XXXXXXXXXX) echo "==> Benchmarking with -f" run func binutils addr2line "-f -i" >> "$log2" #run func elfutils eu-addr2line "-f -i" >> "$log2" run func llvm-sym llvm-symbolizer "-functions=linkage -demangle=0" >> "$log2" for ref in "$@"; do run func "$ref" "$dirname/target/release/addr2line-$ref" "-f -i" >> "$log2" done cat "$log2" | column -t cat "$log2" >> "$log1"; rm "$log2" echo "==> Plotting" Rscript --no-readline --no-restore --no-save "$dirname/bench.plot.r" < "$log1" echo "==> Cleaning up" rm "$log1" exit 0 }