summaryrefslogtreecommitdiffstats
path: root/vendor/addr2line/benchmark.sh
blob: ca4c4f6ece58e6ffa6f898c6d6c45b96f2b612a1 (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
#!/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
}