113 lines
3.0 KiB
Bash
113 lines
3.0 KiB
Bash
|
#!/bin/bash
|
||
|
if [[ $# -le 1 ]]; then
|
||
|
echo "Usage: $0 <executable> [<addresses>] 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
|
||
|
}
|