hackbench run scripts

From: Steven Sistare
Date: Fri Nov 09 2018 - 10:03:25 EST


Hi folks,
I am attaching the bash helper scripts I used to run and post-process hackbench
in case you find them useful. They compute the statistics and print a nicely
formatted result:

feat - Enable/disable one or more sched_features.
runmany - run a command many times and print average time and stdev.
hackdiff - Print difference between 2 identical series of runmany hackbench runs.

You supply the top level script that runs a series of groups. Example:

---- hackseries ---------------
#!/bin/sh

iters=50000
groups="1 2 3 4"
runs=5

tmpfile=temp$$.out
rm -f $tmpfile

runall() {
for g in $groups ; do
echo hackbench $g process $iters | tee -a $tmpfile
runmany $runs hackbench $g process $iters | tee -a $tmpfile
done
}

sudo feat NO_STEAL ; runall ; echo
sudo feat STEAL ; runall ; echo
hackdiff < $tmpfile
rm -f $tmpfile
--------------------------------

$ hackseries
hackbench 1 process 50000
4.096 4.090 4.073 4.129 4.092 Average 4.096 stdev 0.5%
hackbench 2 process 50000
7.215 7.214 7.242 7.208 7.224 Average 7.220 stdev 0.2%
hackbench 3 process 50000
10.082 10.035 10.049 10.068 10.082 Average 10.063 stdev 0.2%
hackbench 4 process 50000
12.851 12.948 12.905 12.916 12.994 Average 12.922 stdev 0.4%

hackbench 1 process 50000
3.193 3.261 3.257 3.223 3.247 Average 3.236 stdev 0.9%
hackbench 2 process 50000
6.020 5.960 6.003 6.008 5.998 Average 5.997 stdev 0.4%
hackbench 3 process 50000
8.598 8.692 8.536 8.661 8.468 Average 8.591 stdev 1.1%
hackbench 4 process 50000
11.201 11.148 11.053 11.174 11.127 Average 11.140 stdev 0.5%

--- base -- --- new ---
groups time %stdev time %stdev %speedup
1 4.096 0.5 3.236 0.9 26.5
2 7.220 0.2 5.997 0.4 20.3
3 10.063 0.2 8.591 1.1 17.1
4 12.922 0.4 11.140 0.5 15.9

- Steve
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Author: Steve Sistare <steven.sistare@xxxxxxxxxx>
#
# Usage: feat [feature1] [feature2] ...
# Enable/disable one or more sched_features.
# With no arguments, print the currently enabled features.

if [[ ! -r /sys/kernel/debug ]]; then
echo "Permission denied. You must be root."
exit 1
elif [[ ! -r /sys/kernel/debug/sched_features ]]; then
echo "debugfs not mounted. Please run as root:"
echo " mount -t debugfs none /sys/kernel/debug"
exit 1
fi

if [ $# == 0 ] ; then
cat /sys/kernel/debug/sched_features | sed 's/ /\n/g'
else
for feat in $* ; do
if ! echo $feat > /sys/kernel/debug/sched_features ; then
echo Unrecognized feature $feat
fi
done
fi

exit 0
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Author: Steve Sistare <steven.sistare@xxxxxxxxxx>
#
# Usage: runmany <repeat> command args ...
# Run command <repeat> times, extract time, and print average and stdev.
#
# Command must print a line of the form "Time %f" (eg, like hackbench).


# Convert float $1 to integral fixed-point value with $2 decimal places.
#
ftoi()
{
declare -i tens=10**$2
echo $(echo "scale=0; ($tens * $1) / 1" | bc -q)
}

# Convert integral fixed-point $1 with $2 decimal places to floating
# point string.
#
itof()
{
declare -i i frac tens x=$1
[[ $x -lt 0 ]] && sign='-' x=(-$x)
tens=10**$2
i=$x/tens
frac=$x%tens
printf "%s%d.%0${2}d" "$sign" $i $frac
}

# Return the average of all arguments.
#
average()
{
declare -i x avg=0

for x in $* ; do
avg=avg+x
done
avg=avg/$#
echo $avg
}

# Return the stdev of all args, as a percent of the average, as a float with
# 6 decimal places.
#
stdev()
{
declare -i x var=0
declare -i avg=$(average $@)

for x in $* ; do
x=x-avg
var=var+x*x
done
echo "scale=6; sqrt($var / ($# - 1)) * 100 / $avg" | bc -q
}

declare -i n=$1
declare -a -i t

if [[ $n -eq 0 ]] ; then
echo "usage: runmany num command args ..."
exit 1
fi

cmd="${@:2:$#}"

for ((i=0; i<$n; i=i+1)) ; do
t1=$($cmd | grep Time | awk '{print $2}')
t[$i]=$(ftoi $t1 3)
printf "%6.3f " $t1
done

avg=$(average ${t[*]})
favg=$(itof avg 3)
std=$(stdev ${t[*]})
printf " Average %.3f stdev %.1f%%\n" $favg $std

#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
#
# Author: Steve Sistare <steven.sistare@xxxxxxxxxx>
#
# Usage: hackdiff
# Print difference between 2 identical series of hackbench runs
#
# Reads lines from stdin of this form (eg, from runmany):
# hackbench 1 process 100000
# 5.753 5.421 5.254 6.044 5.989 Average 5.692 stdev 6.1%
#
# The first occurrence of a hackbench group line is the base series, and the
# next occurrence with identical parameters is the new series.

# Convert float $1 to integral fixed-point value with $2 decimal places
#
ftoi()
{
declare -i tens=10**$2
echo $(echo "scale=0; ($tens * $1) / 1" | bc -q)
}

# Convert integral fixed-point $1 with $2 decimal places to floating point
# string
#
itof()
{
declare -i i frac tens x=$1
tens=10**$2
[[ $x -lt 0 ]] && sign='-' x=(-$x)
i=$x/tens
frac=$x%tens
printf "%s%d.%0${2}d" "$sign" $i $frac
}

declare -a t1 t2 t3 groups
declare -a words
declare -a t1 t2 d1 d2 words groups seen_group
declare -i i t1d t2d t3 n=0

after=false

while read buf ; do
if [[ ${buf:0:9} == "hackbench" ]]; then
words=($buf)
group=${words[1]}
if [[ ${seen_group[$group]} == true ]]; then
if [[ $after == false ]]; then
n=0
after=true
fi
if [[ ${groups[$n]} != $group ]]; then
echo "expected group ${groups[$n]} " \
"but found $group"
exit 1
fi
fi
seen_group[$group]=true
groups[$n]=$group

elif $(echo $buf | grep -q Average) ; then
words=($(echo $buf | sed ' s/^.*Average *//'))
if [[ $after == true ]]; then
t2[$n]=${words[0]}
d=${words[2]}
d2[$n]=${d%\%}
else
t1[$n]=${words[0]}
d=${words[2]}
d1[$n]=${d%\%}
fi
n=($n+1)
fi
done

printf "%21s %13s\n" "--- base --" "--- new ---"
printf "%6s %6s %6s %6s %6s %8s\n" \
groups time \%stdev time \%stdev \%speedup

for ((i=0; i<$n; i++)) ; do
t1d=$(ftoi ${t1[$i]} 3)
t2d=$(ftoi ${t2[$i]} 3)
t3=($t1d*1000/$t2d-1000)
t3=($t3*100)
speedup=$(itof $t3 3)
printf "%6d %6.3f %6.1f %6.3f %6.1f %8.1f\n" \
${groups[$i]} ${t1[$i]} ${d1[$i]} ${t2[$i]} ${d2[$i]} $speedup
done