xtreemfs/contrib/benchmark/benchmark.sh
2020-09-22 02:25:22 +02:00

404 lines
11 KiB
Bash
Executable File

#!/bin/bash
# the timeout for one execution of xtfs_benchmark
TIMEOUT=1500
# the timeout for one cleanup
TIMEOUT_CLEANUP=300
# the time to sleep after a cleanup
SLEEPTIME=600
# if false, the script will not sleep after a cleanup and after drop_caches
# (-v will set false)
SLEEP=true
# the size of the basefile for random benchmarks
BASEFILE_SIZE="100g"
# the directories for the logfiles and the results
LOG_BASE=${BENCH_LOG:-$HOME}
LOG_DIR="$LOG_BASE/log"
RESULT_DIR="$LOG_BASE/result"
# Drops caches after each benchmark. Uncomment to activate
# cp "drop_caches" to "/usr/local/bin" and add "ALL ALL=NOPASSWD: /usr/local/bin/drop_caches" to sudoers file
DROP_CACHES=${BENCH_DROP_CACHES:-"/usr/local/bin/drop_caches"}
if [[ $DROP_CACHES != "false" ]]; then
DROP_CACHES_CALL="sudo ${DROP_CACHES}"
fi
# IP and Port of the DIR
DIR=${BENCH_DIR:-"localhost:32638"}
# IP and Port of the MRC
MRC=${BENCH_MRC:-"localhost:32636"}
# space separed list of OSD_UUIDS, e.g. "osd1 osd2 ..."
OSD_UUIDS=${BENCH_OSD_UUIDS:-"test-osd0"}
# stripe size for a volume
STRIPE_SIZE="128K"
# request size for each I/O operation
REQUEST_SIZE=$STRIPE_SIZE
# replication settings
REPLICATION_POLICY=""
REPLICATION_FACTOR=1
check_env(){
# check XTREEMFS
if [ -z "$XTREEMFS" ]; then
if [ -d java -a -d cpp -a -d etc ]; then
#echo "Looks like you are in an XtreemFS base directory..."
XTREEMFS=`pwd`
elif [ -d ../java -a -d ../cpp -a -d ../etc ]; then
#echo "XTREEMFS base could be the parent directory..."
XTREEMFS=`pwd`/..
fi
fi
if [ ! -e "$XTREEMFS/java/servers/dist/XtreemFS.jar" -a ! -d "$XTREEMFS/java/lib" -a ! -f "/usr/share/java/XtreemFS.jar" ];
then
echo "XtreemFS jar could not be found!"
exit 1
fi
# check JAVA_HOME
if [ -z "$JAVA_HOME" -a ! -f "/usr/bin/java" ]; then
echo "\$JAVA_HOME not set, JDK/JRE 1.6 required"
exit 1
fi
if [ -z "$JAVA_HOME" ]; then
JAVA_HOME=/usr
fi
}
printUsage() {
cat << EOF
Synopsis
$(basename $0) -t TYPE -s NUMBER [-x NUMBER] [-p POLICY -f NUMBER] [-b NUMBER -e NUMBER] [-r NUMBER] [-v]
Run a XtreemFS benchmark series, i.e. a series of benchmarks with increasing
numbers of threads. Logs are placed in \$HOME/log/, results in \$HOME/results
(can be changed at the head of the script).
-t type
Type of benchmarks to run. Type can be either of the following:
sw sequential write
usw unaligned sequential write
sr sequential read
rw random write
rr random read
-s size
Size of one benchmark, modifier K (for KiB), M (for MiB) or G (for GiB) is mandatory.
-c size
Size of each read/write request, modifier K (for KiB), M (for MiB) or G (for GiB) is mandatory.
Defaults to 128K.
-i size
Stripe size for each volume, modifier K (for KiB), M (for MiB) or G (for GiB) is mandatory.
Defaults to 128K.
-p policy
Replication policy to use. Defaults to none.
-f factor
Replication factor to use. Defaults to 1.
-b number of threads to beginn the benchmark series
Minimum number of threads to be run as the benchmarks series.
The series will run benchmarks between the 'begin' and the 'end' number of threads.
-e number of threads to end the benchmark series
Maximum number of threads to be run as the benchmarks series.
The series will run benchmarks between the 'begin' and the 'end' number of threads.
-r repetitions
Number of times a benchmark is repeated.
-v verbose
If set, bash debugging is enabled ('set -x') and sleeping after the benchmarks
is disabled.
EOF
}
init_params(){
check_env
if ! [ -d $LOG_DIR ]; then
echo "$LOG_DIR doesn't existing. Creating $LOG_DIR..."
mkdir -p $LOG_DIR
fi
if ! [ -d $RESULT_DIR ]; then
echo "$RESULT_DIR doesn't existing. Creating $RESULT_DIR"
mkdir -p $RESULT_DIR
fi
THREADS="$(seq $BEGIN $END)"
REPETITIONS="$(seq 1 $REPETITIONS)"
# use second resolution in case multiple benchmarks are run per minute
NOW=$(date +"%y-%m-%d_%H-%M-%S")
# redirect stdout and stderr
exec 2> >(tee $LOG_DIR/$TYPE-$NOW.log)
exec > >(tee $RESULT_DIR/$TYPE-$NOW.csv)
BASEFILE_SIZE=$(parse_size $BASEFILE_SIZE)
REQUEST_SIZE=$(parse_size $REQUEST_SIZE)
STRIPE_SIZE=$(parse_size $STRIPE_SIZE)
}
parse_size(){
local size_with_modifier=$1
local index=$(echo `expr match $size_with_modifier '[0-9]\+'`)
local size=${size_with_modifier:0:$index}
local modifier=${size_with_modifier:$index}
if [ $index != ${#size_with_modifier} ]; then
if [ $modifier = "K" ] || [ $modifier = "k" ]; then
size=$(echo "$size*2^10" | bc)
elif [ $modifier = "M" ] || [ $modifier = "m" ]; then
size=$(echo "$size*2^20" | bc)
elif [ $modifier = "G" ] || [ $modifier = "g" ]; then
size=$(echo "$size*2^30" | bc)
else
echo "Wrong size modifier. Only 'M' and 'G' are allowed"
exit 1
fi
fi
echo $size
}
prepare_seq_read(){
local size=$1
local threads=$2
# declare array of volume names
local volume_index=$(echo "$threads-1" | bc)
for i in $(seq 0 $volume_index); do VOLUMES[$i]=benchmark$i; done
echo -e "\nPreparing sequential read benchmarks\n" >&2
for i in $(seq 1 $threads); do
local index=$(echo "$i-1"|bc)
timeout --foreground $TIMEOUT $XTREEMFS/bin/xtfs_benchmark -sw -ssize $1 --no-cleanup --user $USER \
${VOLUMES[$index]} --stripe-size $STRIPE_SIZE --chunk-size $REQUEST_SIZE
done
}
prepare_random(){
local threads=$1
# declare array of volume names
local volume_index=$(echo "$threads-1" | bc)
for i in $(seq 0 $volume_index); do VOLUMES[$i]=benchmark$i; done
# calc basefile size and round to a number divideable through REQUEST_SIZE
local basefile_size=$(echo "(($BASEFILE_SIZE/$threads)/$REQUEST_SIZE)*$REQUEST_SIZE" | bc)
echo -e "\nPreparing random benchmark: Creating a basefiles\n" >&2
for i in $(seq 1 $threads); do
local index=$(echo "$i-1"|bc)
timeout --foreground $TIMEOUT $XTREEMFS/bin/xtfs_benchmark -rr -rsize $REQUEST_SIZE --no-cleanup-basefile --no-cleanup-volumes --user $USER \
--basefile-size $basefile_size ${VOLUMES[$index]} --stripe-size $STRIPE_SIZE --chunk-size $REQUEST_SIZE
done
}
run_benchmark(){
local benchType=$1
local size=$2
local threads=$3
local replicationOpt=""
if [[ $REPLICATION_POLICY != "" ]]; then
replicationOpt="--replication-policy $REPLICATION_POLICY"
fi
if [ $benchType = "sr" ]; then
XTREEMFS=$XTREEMFS timeout --foreground $TIMEOUT $XTREEMFS/bin/xtfs_benchmark -$benchType -ssize $size -n $threads --no-cleanup-volumes --user $USER \
$replicationOpt --replication-factor $REPLICATION_FACTOR --chunk-size $REQUEST_SIZE --stripe-size $STRIPE_SIZE
elif [ $benchType = "sw" ] || [ $benchType = "usw" ]; then
XTREEMFS=$XTREEMFS timeout --foreground $TIMEOUT $XTREEMFS/bin/xtfs_benchmark -$benchType -ssize $size -n $threads --user $USER \
$replicationOpt --replication-factor $REPLICATION_FACTOR --chunk-size $REQUEST_SIZE --stripe-size $STRIPE_SIZE
elif [ $benchType = "rw" ] || [ $benchType = "rr" ]; then
# calc basefile size and round to a number divideable through REQUEST_SIZE
local basefile_size=$(echo "(($BASEFILE_SIZE/$threads)/$REQUEST_SIZE)*$REQUEST_SIZE" | bc)
XTREEMFS=$XTREEMFS timeout --foreground $TIMEOUT $XTREEMFS/bin/xtfs_benchmark -$benchType -rsize $size --basefile-size $basefile_size -n $threads \
--no-cleanup-basefile --no-cleanup-volumes --user $USER \
$replicationOpt --replication-factor $REPLICATION_FACTOR --chunk-size $REQUEST_SIZE --stripe-size $STRIPE_SIZE
fi
local bench_exit_status=$?
if [ $bench_exit_status -eq 124 ]; then
echo "The benchmark timed out (Timeout: $TIMEOUT)" >&2
interrupted_exit
elif [ $bench_exit_status -ne 0 ]; then
echo "The benchmark did not finish with exit status 0" >&2
interrupted_exit
fi
# cleanup after *every* benchmark only for seq write benchmark
if [ $benchType = "sr" ]; then
cleanup_osd
fi
}
delete_volumes(){
local number_of_threads=$1
local volume_index=$(echo "$number_of_threads-1" | bc)
for i in $(seq 0 $volume_index); do
rmfs.xtreemfs -f $MRC/benchmark$i >/dev/null
if [ $? -eq 0 ]; then
echo "Removed volume benchmark$i" >&2
fi
done
}
cleanup_osd(){
for osd in $OSD_UUIDS; do
timeout --foreground $TIMEOUT_CLEANUP $XTREEMFS/bin/xtfs_cleanup -dir pbrpc://$DIR -wait -e -delete_volumes uuid:$osd >&2
done
if $SLEEP; then
echo "Start Sleeping for $(echo "$SLEEPTIME/60"|bc) minutes at $(date)" >&2
sleep $SLEEPTIME
echo "Finished Sleeping at $(date)" >&2
fi
drop_caches
}
interrupted_exit(){
echo "Unexpected exit, cleaning up..." >&2
SLEEP=false
delete_volumes $END
cleanup_osd
exit 1
}
drop_caches(){
if [ -n "$DROP_CACHES_CALL" ]; then
echo "Dropping caches" >&2
$DROP_CACHES_CALL
if $SLEEP; then
sleep 10
fi
fi
}
##### main ###
trap "echo; echo 'Interrupt received '; interrupted_exit" INT
# show usage if invoked without options/arguments
if [ $# -eq 0 ]; then
printUsage
exit 1
fi
# default values
BEGIN=1
END=1
REPETITIONS=1
# parse options
while getopts ":t:s:c:i:b:e:r:p:f:v" opt; do
case $opt in
t)
if [ $OPTARG = "sw" ] || [ $OPTARG = "usw" ] || [ $OPTARG = "sr" ] || [ $OPTARG = "rw" ] || [ $OPTARG = "rr" ]; then
TYPE=$OPTARG
else
echo 'wrong argument to -t. Needs to be either "sw", "usw", "sr", "rw" or "rr"'
exit 1
fi
;;
s)
SIZE=$(parse_size $OPTARG)
;;
c)
REQUEST_SIZE=$(parse_size $OPTARG)
;;
i)
STRIPE_SIZE=$(parse_size $OPTARG)
;;
b)
BEGIN=$OPTARG
;;
e)
END=$OPTARG
;;
r)
REPETITIONS=$OPTARG
;;
p)
REPLICATION_POLICY=$OPTARG
;;
f)
REPLICATION_FACTOR=$OPTARG
;;
v)
SLEEP=false
set -x
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
init_params
drop_caches
echo "Running:" $0 $@ >&2
for i in $THREADS; do
size="$(echo "$SIZE/$i"|bc)"
if [ $TYPE != "usw" ]; then
size="$(echo "($size/$REQUEST_SIZE)*$REQUEST_SIZE" | bc)" # round down to a size divideable through the REQUEST_SIZE
fi
if [ $TYPE = "sr" ]; then
prepare_seq_read $size $i
cleanup_osd
elif [ $TYPE = "rw" ] || [ $TYPE = "rr" ]; then
prepare_random $i
fi
for j in $REPETITIONS; do
echo "Start $i-Thread-Benchmark Nr. $j" >&2
run_benchmark $TYPE $size $i
echo "Finished $i-Thread-Benchmark Nr. $j" >&2
done
# seq write benchmarks run cleanup after every benchmark, so this would be redundant
if [ $TYPE != "sw" ] && [ $TYPE != "usw" ]; then
volume_index=$(echo "$i-1" | bc)
for i in $(seq 0 $volume_index); do
rmfs.xtreemfs -f $MRC/benchmark$i >&2
echo "Remove volume benchmark$i" >&2
done
cleanup_osd
fi
done