01-06-2021, 04:00 PM
@sohamb03
The bench.sh -io section of the script -shown above- assumes that all I/O rates are in MB/s which may be a valid general assumption but isn't always true, like in VirMach's VPS-9 @Buffalo :
Any time there is a mixed speed units in the I/O tests, the Average speed will be WRONG!... as a consequence of that assumption.
The fix is to introduce a conversion mechanism that can trap all GB/s units and convert them in MB/s, like HR's did in his own version of the script (see below), or something more general that systematically convert all units into Bytes then format the average result back again in the adhoc unit value (this later method is the one I use in my own disk I/O bench.)
HR's version:
In my script I'm using a dd_conv subroutine that take care of the conversions; it's used like this:
My 'storageBufferedWrite' test which uses the subroutine above:
Feel free to use anyone that suits you most...
Code: (Select All)
iotest () {
echo "Buffered Sequential Write Speed" | tee -a $HOME/bench.log
echo "-------------------------------" | tee -a $HOME/bench.log
# Measuring disk speed with DD
io=$( ( dd if=/dev/zero of=test_$$ bs=64k count=16k conv=fdatasync && rm -f test_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
io2=$( ( dd if=/dev/zero of=test_$$ bs=64k count=16k conv=fdatasync && rm -f test_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
io3=$( ( dd if=/dev/zero of=test_$$ bs=64k count=16k conv=fdatasync && rm -f test_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
# Calculating avg I/O (better approach with awk for non int values)
ioraw=$( echo $io | awk 'NR==1 {print $1}' )
ioraw2=$( echo $io2 | awk 'NR==1 {print $1}' )
ioraw3=$( echo $io3 | awk 'NR==1 {print $1}' )
ioall=$( awk 'BEGIN{print '$ioraw' + '$ioraw2' + '$ioraw3'}' )
ioavg=$( awk 'BEGIN{print '$ioall'/3}' )
# Output of DD result
echo "I/O (1st run) : $io" | tee -a $HOME/bench.log
echo "I/O (2nd run) : $io2" | tee -a $HOME/bench.log
echo "I/O (3rd run) : $io3" | tee -a $HOME/bench.log
echo "Average I/O : $ioavg MB/s" | tee -a $HOME/bench.log
echo "" | tee -a $HOME/bench.log
}
The bench.sh -io section of the script -shown above- assumes that all I/O rates are in MB/s which may be a valid general assumption but isn't always true, like in VirMach's VPS-9 @Buffalo :
Code: (Select All)
# /............/bench.sh
// ) ) || / / // ) ) // ) )
//___/ / ___ ___ __ ___ //___/ / || / / //___/ / ((
/ ____ / // ) ) (( ) ) / / /____ / || / / / ____ / \
// // / / \ \ / / / / ||/ / // ) )
// ((___/ / // ) ) / / / / | / // ((___ / /
FREE VPS PROVIDER - https://post4vps.com
Benchmark started on Mon Jan 4 17:16:03 +01 2021
Full benchmark log: /root/bench.log
(.............................)
Buffered Sequential Write Speed
-------------------------------
I/O (1st run) : 1.1 GB/s
I/O (2nd run) : 987 MB/s
I/O (3rd run) : 978 MB/s
Average I/O : 655.367 MB/s
Any time there is a mixed speed units in the I/O tests, the Average speed will be WRONG!... as a consequence of that assumption.
The fix is to introduce a conversion mechanism that can trap all GB/s units and convert them in MB/s, like HR's did in his own version of the script (see below), or something more general that systematically convert all units into Bytes then format the average result back again in the adhoc unit value (this later method is the one I use in my own disk I/O bench.)
HR's version:
Code: (Select All)
(.......same starting code here.........)
# I/O without units for calculation (better approach with awk for non int values)
ioraw=$( echo $io | awk 'NR==1 {print $1}' )
ioraw2=$( echo $io2 | awk 'NR==1 {print $1}' )
ioraw3=$( echo $io3 | awk 'NR==1 {print $1}' )
# Converting possible GB/s results to MB/s value for proper calculation afterwards
iounit=$( echo $io | awk 'NR==1 {print $2}' )
iounit2=$( echo $io2 | awk 'NR==1 {print $2}' )
iounit3=$( echo $io3 | awk 'NR==1 {print $2}' )
# Converting 1st benchmark run
if [ "$iounit" == "GB/s" ]
then
ioconv=$( bc -l <<<"($ioraw * 1000)" )
ioconv=$( echo ${ioconv%.*} )
else
ioconv=$ioraw
fi
# Converting 2nd benchmark run
if [ "$iounit2" == "GB/s" ]
then
ioconv2=$( bc -l <<<"($ioraw2 * 1000)" )
ioconv2=$( echo ${ioconv2%.*} )
else
ioconv2=$ioraw2
fi
# Converting 3rd benchmark run
if [ "$iounit3" == "GB/s" ]
then
ioconv3=$( bc -l <<<"($ioraw3 * 1000)" )
ioconv3=$( echo ${ioconv3%.*} )
else
ioconv3=$ioraw3
fi
# Calculating all IO results and avg IO
ioall=$( awk 'BEGIN{print '$ioconv' + '$ioconv2' + '$ioconv3'}' )
ioall=$( echo ${ioall%.*} )
ioavg=$( awk 'BEGIN{print '$ioall'/3}' )
ioavg=$( echo ${ioavg%.*} )
ioavggbs=$( echo "scale=2; $ioavg/1000" | bc )
# Output of DD result
echo "I/O (1st run) : $io" | tee -a $HOME/bench.log
echo "I/O (2nd run) : $io2" | tee -a $HOME/bench.log
echo "I/O (3rd run) : $io3" | tee -a $HOME/bench.log
echo "Average I/O : $ioavg MB/s or $ioavggbs GB/s" | tee -a $HOME/bench.log
echo "" | tee -a $HOME/bench.log
In my script I'm using a dd_conv subroutine that take care of the conversions; it's used like this:
Code: (Select All)
dd_conv() {
speed=$1
if [ "$2" == 'GB/s' ] || [ "$2" == "GB/sec" ]; then
speed=$(echo "1000*1000*1000*$1" |bc)
elif [ "$2" == "MB/s" ] || [ "$2" == "MB/sec" ]; then
speed=$(echo "1000*1000*$1" |bc)
elif [ "$2" == 'KB/s' ] || [ "$2" == "KB/sec" ]; then
speed=$(echo "1000*$1" |bc)
elif [ "$2" == 'B/s' ] || [ "$2" == "B/sec" ]; then
speed=$1
fi
echo $speed
}
My 'storageBufferedWrite' test which uses the subroutine above:
Code: (Select All)
storageBufferedWrite(){
printf '\n'
echo "Testing storage buffered write speed."
avgRate=0
iter=3
sync
for i in {1..3}; do
printf 'Pass %s... ' $i
io=$( ( dd if=/dev/zero of=test_$$ oflag=nocache conv=notrunc,fdatasync count=0 bs=64k count=16k ) 2>&1 | awk -F, '{io=$NF} END { print io}'; rm -f test_$$ )
echo $io
speed=$( dd_conv $io )
avgRate=$(echo "$avgRate + $speed" | bc)
done
avgRate=$(echo "$avgRate / $iter" | bc)
avgRate=$( formater $avgRate)
echo "Buffered Write Speed = $avgRate"
}
Feel free to use anyone that suits you most...