1#!/bin/bash 2if [[ $# -le 1 ]]; then 3 echo "Usage: $0 <executable> [<addresses>] REFS..." 4 exit 1 5fi 6target="$1" 7shift 8 9addresses="" 10if [[ -e "$1" ]]; then 11 addresses="$1" 12 shift 13fi 14 15# path to "us" 16# readlink -f, but more portable: 17dirname=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$(dirname "$0")") 18 19# http://stackoverflow.com/a/2358432/472927 20{ 21 # compile all refs 22 pushd "$dirname" > /dev/null 23 # if the user has some local changes, preserve them 24 nstashed=$(git stash list | wc -l) 25 echo "==> Stashing any local modifications" 26 git stash --keep-index > /dev/null 27 popstash() { 28 # http://stackoverflow.com/q/24520791/472927 29 if [[ "$(git stash list | wc -l)" -ne "$nstashed" ]]; then 30 echo "==> Restoring stashed state" 31 git stash pop > /dev/null 32 fi 33 } 34 # if the user has added stuff to the index, abort 35 if ! git diff-index --quiet HEAD --; then 36 echo "Refusing to overwrite outstanding git changes" 37 popstash 38 exit 2 39 fi 40 current=$(git symbolic-ref --short HEAD) 41 for ref in "$@"; do 42 echo "==> Compiling $ref" 43 git checkout -q "$ref" 44 commit=$(git rev-parse HEAD) 45 fn="target/release/addr2line-$commit" 46 if [[ ! -e "$fn" ]]; then 47 cargo build --release --example addr2line 48 cp target/release/examples/addr2line "$fn" 49 fi 50 if [[ "$ref" != "$commit" ]]; then 51 ln -sfn "addr2line-$commit" target/release/addr2line-"$ref" 52 fi 53 done 54 git checkout -q "$current" 55 popstash 56 popd > /dev/null 57 58 # get us some addresses to look up 59 if [[ -z "$addresses" ]]; then 60 echo "==> Looking for benchmarking addresses (this may take a while)" 61 addresses=$(mktemp tmp.XXXXXXXXXX) 62 objdump -C -x --disassemble -l "$target" \ 63 | grep -P '0[048]:' \ 64 | awk '{print $1}' \ 65 | sed 's/:$//' \ 66 > "$addresses" 67 echo " -> Addresses stored in $addresses; you should re-use it next time" 68 fi 69 70 run() { 71 func="$1" 72 name="$2" 73 cmd="$3" 74 args="$4" 75 printf "%s\t%s\t" "$name" "$func" 76 if [[ "$cmd" =~ llvm-symbolizer ]]; then 77 /usr/bin/time -f '%e\t%M' "$cmd" $args -obj="$target" < "$addresses" 2>&1 >/dev/null 78 else 79 /usr/bin/time -f '%e\t%M' "$cmd" $args -e "$target" < "$addresses" 2>&1 >/dev/null 80 fi 81 } 82 83 # run without functions 84 log1=$(mktemp tmp.XXXXXXXXXX) 85 echo "==> Benchmarking" 86 run nofunc binutils addr2line >> "$log1" 87 #run nofunc elfutils eu-addr2line >> "$log1" 88 run nofunc llvm-sym llvm-symbolizer -functions=none >> "$log1" 89 for ref in "$@"; do 90 run nofunc "$ref" "$dirname/target/release/addr2line-$ref" >> "$log1" 91 done 92 cat "$log1" | column -t 93 94 # run with functions 95 log2=$(mktemp tmp.XXXXXXXXXX) 96 echo "==> Benchmarking with -f" 97 run func binutils addr2line "-f -i" >> "$log2" 98 #run func elfutils eu-addr2line "-f -i" >> "$log2" 99 run func llvm-sym llvm-symbolizer "-functions=linkage -demangle=0" >> "$log2" 100 for ref in "$@"; do 101 run func "$ref" "$dirname/target/release/addr2line-$ref" "-f -i" >> "$log2" 102 done 103 cat "$log2" | column -t 104 cat "$log2" >> "$log1"; rm "$log2" 105 106 echo "==> Plotting" 107 Rscript --no-readline --no-restore --no-save "$dirname/bench.plot.r" < "$log1" 108 109 echo "==> Cleaning up" 110 rm "$log1" 111 exit 0 112} 113