@@ -2,16 +2,20 @@
3print_help () {
3print_help () {
4 echo "Usage: $0 "
4 echo "Usage: $0 "
5− echo " [--quick] [--append] "
6− echo " [--no-graphs] [--no-measure]"
7− echo " [--benchmark <linear|nested>]"
8 echo " [--compare] [--base commit] [--candidate commit]"
5 echo " [--compare] [--base commit] [--candidate commit]"
6+ echo " [--benchmark <linear|nested|base>]"
9+ echo " [--no-measure]"
9 echo " -- <gauge options>"
11 echo " -- <gauge options>"
13+ # XXX in the report the base and candidate are shown in reverse order as we
14+ # run the benchmarks for candidate first and then base.
11− echo "When using --compare, by default comparative chart of HEAD^ vs HEAD"
15+ #echo "When using --compare, by default comparative chart of HEAD^ vs HEAD"
12− echo "commit is generated, in the 'charts' directory."
16+ #echo "commit is generated, in the 'charts' directory."
13− echo "Use --base and --candidate to select the commits to compare."
17+ #echo "Use --base and --candidate to select the commits to compare."
15 echo "Any arguments after a '--' are passed directly to guage"
19 echo "Any arguments after a '--' are passed directly to guage"
16 echo "You can omit '--' if the gauge args used do not start with a '-'."
20 echo "You can omit '--' if the gauge args used do not start with a '-'."
@@ -23,61 +27,64 @@ die () {
26−DEFAULT_BENCHMARK=linear
30+set_benchmarks() {
27−COMPARE=0
31+ if test -z "$BENCHMARKS"
29−while test -n "$1"
33+ BENCHMARKS=$DEFAULT_BENCHMARKS
30−do
34+ echo "Using default benchmark suite [$BENCHMARKS], use --benchmark to specify another"
32− -h|--help|help) print_help ;;
36+ echo "Using benchmark suite [$BENCHMARKS]"
33− --quick) QUICK=1; shift ;;
37+ fi
34− --append) APPEND=1; shift ;;
38+}
35− --benchmark) shift; BENCHMARK=$1; shift ;;
36− --base) shift; BASE=$1; shift ;;
37− --candidate) shift; CANDIDATE=$1; shift ;;
38− --compare) COMPARE=1; shift ;;
39− --no-graphs) GRAPH=0; shift ;;
40− --no-measure) MEASURE=0; shift ;;
42− -*|--*) print_help ;;
47−GAUGE_ARGS=$*
40+# $1: benchmark name (linear, nested, base)
43+ local prog_name="chart-$bench_name"
45+ local prog_path=$($STACK exec which $prog_name)
46+ if test -x "$prog_path"
49−if test -z "$BENCHMARK"
54+# $1: benchmark name (linear, nested, base)
50−then
55+build_report_prog() {
51− BENCHMARK=$DEFAULT_BENCHMARK
56+ local bench_name=$1
52− echo "Using default benchmark suite [$BENCHMARK], use --benchmark to specify another"
57+ local prog_name="chart-$bench_name"
53−else
58+ local prog_path=$($STACK exec which $prog_name)
54− echo "Using benchmark suite [$BENCHMARK]"
57−STACK=stack
60+ hash -r
58−echo "Using stack command [$STACK]"
61+ if test ! -x "$prog_path" -a "$BUILD_ONCE" = "0"
63+ echo "Building bench-graph executables"
65+ $STACK build --flag "streamly:dev" || die "build failed"
66+ elif test ! -x "$prog_path"
60−# We build it first at the current commit before checking out any other commit
73+build_report_progs() {
61−# for benchmarking.
74+ local bench_list=$1
62−if test "$GRAPH" != "0"
64− CHART_PROG="chart-$BENCHMARK"
65− prog=$($STACK exec which $CHART_PROG)
69− echo "Building charting executable"
70− $STACK build --flag "streamly:dev" || die "build failed"
73− prog=$($STACK exec which $CHART_PROG)
74− if test ! -x "$prog"
76+ if test "$RAW" = "0"
76− die "Could not find [$CHART_PROG] executable"
78+ for i in $bench_list
80+ build_report_prog $i || exit 1
82+ prog=$(find_report_prog $i) || \
83+ die "Cannot find bench-graph executable for benchmark $i"
84+ echo "Using bench-graph executable [$prog]"
79− echo "Using chart executable [$CHART_PROG]"
82# We run the benchmarks in isolation in a separate process so that different
89# We run the benchmarks in isolation in a separate process so that different
83# benchmarks do not interfere with other. To enable that we need to pass the
90# benchmarks do not interfere with other. To enable that we need to pass the
@@ -89,16 +96,21 @@ fi
89# find .stack-work/ -type f -name "benchmarks"
96# find .stack-work/ -type f -name "benchmarks"
91find_bench_prog () {
98find_bench_prog () {
92− BENCH_PROG=`$STACK path --dist-dir`/build/$BENCHMARK/$BENCHMARK
100+ local bench_prog=`$STACK path --dist-dir`/build/$bench_name/$bench_name
93− if test ! -x "$BENCH_PROG"
101+ if test -x "$bench_prog"
95− echo
103+ echo $bench_prog
96− echo "WARNING! benchmark binary [$BENCH_PROG] not found or not executable"
104+ else
97− echo "WARNING! not using isolated measurement."
105+ return 1
109+bench_output_file() {
111+ echo "charts/$bench_name/results.csv"
102# --min-duration 0 means exactly one iteration per sample. We use a million
114# --min-duration 0 means exactly one iteration per sample. We use a million
103# iterations in the benchmarking code explicitly and do not use the iterations
115# iterations in the benchmarking code explicitly and do not use the iterations
104# done by the benchmarking tool.
116# done by the benchmarking tool.
@@ -112,44 +124,33 @@ find_bench_prog () {
112# We can pass --min-samples value from the command line as second argument
124# We can pass --min-samples value from the command line as second argument
113# after the benchmark name in case we want to use more than one sample.
125# after the benchmark name in case we want to use more than one sample.
115−if test "$QUICK" = "1"
127+run_bench () {
116−then
128+ local bench_name=$1
117− ENABLE_QUICK="--quick"
129+ local output_file=$(bench_output_file $bench_name)
118−fi
130+ local bench_prog
131+ bench_prog=$(find_bench_prog $bench_name) || \
132+ die "Cannot find benchmark executable for benchmark $bench_name"
120−OUTPUT_FILE="charts/results.csv"
134+ mkdir -p `dirname $output_file`
122−run_bench () {
136+ echo "Running benchmark $bench_name ..."
123− $STACK build --bench --no-run-benchmarks || die "build failed"
137+
124− find_bench_prog
138+ $bench_prog $SPEED_OPTIONS \
125− mkdir -p charts
139+ --csvraw=$output_file \
127− # We set min-samples to 3 if we use less than three samples, statistical
128− # analysis crashes. Note that the benchmark runs for a minimum of 5 seconds.
129− # We use min-duration=0 to run just one iteration for each sample. Anyway the
130− # default is to run iterations worth minimum 30 ms and most of our benchmarks
131− # are close to that or more.
132− $BENCH_PROG $ENABLE_QUICK \
133− --include-first-iter \
137− --csvraw=$OUTPUT_FILE \
139− --measure-with $BENCH_PROG $GAUGE_ARGS || die "Benchmarking failed"
141+ --measure-with $bench_prog $GAUGE_ARGS || die "Benchmarking failed"
142−if test "$MEASURE" != "0"
144+run_benches() {
143− then
145+ for i in $1
144− if test -e $OUTPUT_FILE -a "$APPEND" != 1
146+ do
145− then
147+ run_bench $i
146− mv -f -v $OUTPUT_FILE ${OUTPUT_FILE}.prev
148+ done
151+run_benches_comparing() {
149− if test "$COMPARE" = "0"
153 if test -z "$CANDIDATE"
154 if test -z "$CANDIDATE"
155 CANDIDATE=$(git rev-parse HEAD)
156 CANDIDATE=$(git rev-parse HEAD)
@@ -161,18 +162,132 @@ if test "$MEASURE" != "0"
162 echo "Checking out base commit for benchmarking"
163 echo "Checking out base commit for benchmarking"
163 git checkout "$BASE" || die "Checkout of base commit failed"
164 git checkout "$BASE" || die "Checkout of base commit failed"
166+ run_benches "$bench_list"
165 echo "Checking out candidate commit for benchmarking"
168 echo "Checking out candidate commit for benchmarking"
166 git checkout "$CANDIDATE" || die "Checkout of candidate commit failed"
169 git checkout "$CANDIDATE" || die "Checkout of candidate commit failed"
171+ run_benches "$bench_list"
172+ # XXX reset back to the original commit
175+backup_output_file() {
177+ local output_file=$(bench_output_file $bench_name)
179+ if test -e $output_file -a "$APPEND" != 1
181+ mv -f -v $output_file ${output_file}.prev
188+ for i in $bench_list
190+ backup_output_file $i
193+ if test "$COMPARE" = "0"
195+ run_benches "$bench_list"
197+ run_benches_comparing "$bench_list"
205+ if test "$RAW" = "0"
208+ prog=$(find_report_prog $bench_name) || \
209+ die "Cannot find bench-graph executable for benchmark $bench_name"
211+ echo "Generating reports for ${bench_name}..."
223+#-----------------------------------------------------------------------------
224+# Execution starts here
225+#-----------------------------------------------------------------------------
227+DEFAULT_BENCHMARKS="linear"
237+SPEED_OPTIONS="--quick --min-samples 10 --time-limit 1 --min-duration 0"
171−if test "$GRAPH" != "0"
239+STACK=stack
244+#-----------------------------------------------------------------------------
246+#-----------------------------------------------------------------------------
251+ -h|--help|help) print_help ;;
252+ --slow) SPEED_OPTIONS="--min-duration 0"; shift ;;
253+ --append) APPEND=1; shift ;;
254+ --benchmark) shift; BENCHMARKS=$1; shift ;;
255+ --base) shift; BASE=$1; shift ;;
256+ --candidate) shift; CANDIDATE=$1; shift ;;
257+ --compare) COMPARE=1; shift ;;
258+ --raw) RAW=1; shift ;;
259+ --graphs) GRAPH=1; shift ;;
260+ --no-measure) MEASURE=0; shift ;;
262+ -*|--*) print_help ;;
268+echo "Using stack command [$STACK]"
271+#-----------------------------------------------------------------------------
273+#-----------------------------------------------------------------------------
275+# We need to build the report progs first at the current (latest) commit before
276+# checking out any other commit for benchmarking.
277+build_report_progs "$BENCHMARKS"
279+#-----------------------------------------------------------------------------
281+#-----------------------------------------------------------------------------
283+if test "$MEASURE" = "1"
173− echo
285+ $STACK build --bench --no-run-benchmarks || die "build failed"
174− echo "Generating charts from ${OUTPUT_FILE}..."
286+ run_measurements "$BENCHMARKS"
178−# XXX reset back to the original commit
289+#-----------------------------------------------------------------------------
291+#-----------------------------------------------------------------------------
293+run_reports "$BENCHMARKS"