diff --git a/README.md b/README.md index 119e410..a048cfd 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ This script has been tested on the following Linux distributions: CentOS 6+, Deb **Local fio/iperf3 Packages**: If the tested system has fio and/or iperf3 already installed, the local package will take precedence over the precompiled binary. +**Experimental ARM Compatibility**: Initial ARM compatibilty has been introduced, however, is not considered entirely stable due to limited testing on distinct ARM devices. Report any errors or issues. + **IPv6-Only Machines**: The above command will not work on IPv6-only machines. [See below](#ipv6-only-machines). **High Bandwidth Usage Notice**: By default, this script will perform many iperf network tests, which will try to max out the network port for ~20s per location (10s in each direction). Low-bandwidth servers (such as a NAT VPS) should consider running this script with the `-r` flag (for reduced iperf locations) or the `-i` flag (to disable network tests entirely). diff --git a/bin/README.md b/bin/README.md index e5d2bfa..d355c8a 100644 --- a/bin/README.md +++ b/bin/README.md @@ -9,6 +9,15 @@ This directory contains all of the binaries required to run the benchmarking tes * **iperf_x64** - v3.10 (compiled 28 May 2021) - 64-bit version * **iperf_x86** - v3.10 (compiled 28 May 2021) - 32-bit version +### ARM Binaries + +ARM compatibilty is considered experimental. Static binaries for ARM-based machines are cross-compiled within a Holy Build Box container using the [musl toolchain](https://musl.cc/). + +* **fio_aarch64** - v3.27 (compiled 05 June 2021) - ARM 64-bit version +* **fio_arm** - v3.27 (compiled 05 June 2021) - ARM 32-bit version +* **iperf_aarch64** - v3.10 (compiled 05 June 2021) - ARM 64-bit version +* **iperf_arm** - v3.10 (compiled 05 June 2021) - ARM 32-bit version + ### Compile Notes **Pre-reqs**: @@ -27,3 +36,21 @@ docker run -t -i --rm -v `pwd`:/io phusion/holy-build-box-32:latest linux32 bash ``` 64-bit and 32-bit binaries will be placed in the current directory. + +### ARM Compile Notes + +Compilation of ARM-compatible binaries requires additional environment variables to identify the proper musl toolchain and architecture to target for cross-compilation. + +**Compiling 64-bit binaries**: + +```sh +docker run -t -i --rm -v `pwd`:/io --env ARCH=aarch64 --env CROSS=aarch64-linux-musl --env HOST=aarch64-linux-gnu phusion/holy-build-box-64:latest bash /io/compile-arm.sh +``` + +**Compiling 32-bit binaries**: + +```sh +docker run -t -i --rm -v `pwd`:/io --env ARCH=arm --env CROSS=arm-linux-musleabihf --env HOST=arm-linux-gnueabihf phusion/holy-build-box-64:latest bash /io/compile-arm.sh +``` + +64-bit (aarch64) and 32-bit (arm) binaries will be placed in the current directory. diff --git a/bin/compile-arm.sh b/bin/compile-arm.sh new file mode 100755 index 0000000..708bb61 --- /dev/null +++ b/bin/compile-arm.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -e + +# Activate Holy Build Box lib compiliation environment +source /hbb/activate + +set -x + +yum install -y yum-plugin-ovl # fix for docker overlay fs +yum install -y xz + +# download musl cross compilation toolchain +cd ~ +curl -L "https://musl.cc/${CROSS}-cross.tgz" -o "${CROSS}-cross.tgz" +tar xf ${CROSS}-cross.tgz + +# download, compile, and install libaio as static library +cd ~ +curl -L http://ftp.de.debian.org/debian/pool/main/liba/libaio/libaio_0.3.112.orig.tar.xz -o "libaio.tar.xz" +tar xf libaio.tar.xz +cd libaio-*/src +CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ENABLE_SHARED=0 make prefix=/hbb_exe install + +# Activate Holy Build Box exe compilation environment +source /hbb_exe/activate + +# download and compile fio +cd ~ +curl -L https://github.com/axboe/fio/archive/fio-3.27.tar.gz -o "fio.tar.gz" +tar xf fio.tar.gz +cd fio-fio* +CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-native --build-static +make + +# verify no external shared library links +libcheck fio +# copy fio binary to mounted dir +cp fio /io/fio_$ARCH + +# download and compile iperf +cd ~ +curl -L https://github.com/esnet/iperf/archive/3.10.tar.gz -o "iperf.tar.gz" +tar xf iperf.tar.gz +cd iperf* +CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-shared --disable-profiling --build x86_64-pc-linux-gnu --host ${HOST} --with-openssl=no --enable-static-bin +make + +# verify no external shared library links +libcheck src/iperf3 +# copy iperf binary to mounted dir +cp src/iperf3 /io/iperf3_$ARCH diff --git a/bin/fio_aarch64 b/bin/fio_aarch64 new file mode 100755 index 0000000..49ca264 Binary files /dev/null and b/bin/fio_aarch64 differ diff --git a/bin/fio_arm b/bin/fio_arm new file mode 100755 index 0000000..5406893 Binary files /dev/null and b/bin/fio_arm differ diff --git a/bin/iperf3_aarch64 b/bin/iperf3_aarch64 new file mode 100755 index 0000000..7287475 Binary files /dev/null and b/bin/iperf3_aarch64 differ diff --git a/bin/iperf3_arm b/bin/iperf3_arm new file mode 100755 index 0000000..fd7309c Binary files /dev/null and b/bin/iperf3_arm differ diff --git a/yabs.sh b/yabs.sh index 01a7273..41d45a9 100755 --- a/yabs.sh +++ b/yabs.sh @@ -1,7 +1,7 @@ #!/bin/bash # Yet Another Bench Script by Mason Rowe -# Initial Oct 2019; Last update May 2021 +# Initial Oct 2019; Last update June 2021 # # Disclaimer: This project is a work in progress. Any errors or suggestions should be # relayed to me via the GitHub project page linked below. @@ -15,7 +15,7 @@ echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #' echo -e '# Yet-Another-Bench-Script #' -echo -e '# v2021-05-28 #' +echo -e '# v2021-06-05 #' echo -e '# https://github.com/masonr/yet-another-bench-script #' echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #' @@ -33,6 +33,16 @@ if [[ $ARCH = *x86_64* ]]; then elif [[ $ARCH = *i?86* ]]; then # host is running a 32-bit kernel ARCH="x86" +elif [[ $ARCH = *aarch* || $ARCH = *arm* ]]; then + KERNEL_BIT=`getconf LONG_BIT` + if [[ $KERNEL_BIT = *64* ]]; then + # host is running an ARM 64-bit kernel + ARCH="aarch64" + else + # host is running an ARM 32-bit kernel + ARCH="arm" + fi + echo -e "\nARM-compatibility is considered *experimental*" else # host is running a non-supported kernel echo -e "Architecture not supported by YABS." @@ -155,10 +165,20 @@ function format_size { echo -e echo -e "Basic System Information:" echo -e "---------------------------------" -CPU_PROC=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//') +if [[ $ARCH = *aarch64* || $ARCH = *arm* ]]; then + CPU_PROC=$(lscpu | grep "Model name" | sed 's/Model name: *//g') +else + CPU_PROC=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//') +fi echo -e "Processor : $CPU_PROC" -CPU_CORES=$(awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo) -CPU_FREQ=$(awk -F: ' /cpu MHz/ {freq=$2} END {print freq " MHz"}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//') +if [[ $ARCH = *aarch64* || $ARCH = *arm* ]]; then + CPU_CORES=$(lscpu | grep "CPU(s):" | sed 's/CPU(s): *//g') + CPU_FREQ=$(lscpu | grep "CPU max MHz" | sed 's/CPU max MHz: *//g') + CPU_FREQ="${CPU_FREQ} MHz" +else + CPU_CORES=$(awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo) + CPU_FREQ=$(awk -F: ' /cpu MHz/ {freq=$2} END {print freq " MHz"}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//') +fi echo -e "CPU cores : $CPU_CORES @ $CPU_FREQ" CPU_AES=$(cat /proc/cpuinfo | grep aes) [[ -z "$CPU_AES" ]] && CPU_AES="\xE2\x9D\x8C Disabled" || CPU_AES="\xE2\x9C\x94 Enabled" @@ -273,9 +293,15 @@ function format_iops { # Parameters: # - (none) function disk_test { + if [[ "$ARCH" = "aarch64" || "$ARCH" = "arm" ]]; then + FIO_SIZE=512M + else + FIO_SIZE=2G + fi + # run a quick test to generate the fio test file to be used by the actual tests echo -en "Generating fio test file..." - $FIO_CMD --name=setup --ioengine=libaio --rw=read --bs=4k --iodepth=64 --numjobs=2 --size=2G --runtime=1 --gtod_reduce=1 --filename=$DISK_PATH/test.fio --direct=1 --minimal &> /dev/null + $FIO_CMD --name=setup --ioengine=libaio --rw=read --bs=64k --iodepth=64 --numjobs=2 --size=$FIO_SIZE --runtime=1 --gtod_reduce=1 --filename=$DISK_PATH/test.fio --direct=1 --minimal &> /dev/null echo -en "\r\033[0K" # get array of block sizes to evaluate @@ -284,7 +310,7 @@ function disk_test { for BS in "${BLOCK_SIZES[@]}"; do # run rand read/write mixed fio test with block size = $BS echo -en "Running fio random mixed R+W disk test with $BS block size..." - DISK_TEST=$(timeout 35 $FIO_CMD --name=rand_rw_$BS --ioengine=libaio --rw=randrw --rwmixread=50 --bs=$BS --iodepth=64 --numjobs=2 --size=2G --runtime=30 --gtod_reduce=1 --direct=1 --filename=$DISK_PATH/test.fio --group_reporting --minimal 2> /dev/null | grep rand_rw_$BS) + DISK_TEST=$(timeout 35 $FIO_CMD --name=rand_rw_$BS --ioengine=libaio --rw=randrw --rwmixread=50 --bs=$BS --iodepth=64 --numjobs=2 --size=$FIO_SIZE --runtime=30 --gtod_reduce=1 --direct=1 --filename=$DISK_PATH/test.fio --group_reporting --minimal 2> /dev/null | grep rand_rw_$BS) DISK_IOPS_R=$(echo $DISK_TEST | awk -F';' '{print $8}') DISK_IOPS_W=$(echo $DISK_TEST | awk -F';' '{print $49}') DISK_IOPS=$(format_iops $(awk -v a="$DISK_IOPS_R" -v b="$DISK_IOPS_W" 'BEGIN { print a + b }')) @@ -340,8 +366,10 @@ function dd_test { # check if disk performance is being tested and the host has required space (2G) AVAIL_SPACE=`df -k . | awk 'NR==2{print $4}'` -if [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 2097152 ]]; then # 2GB = 2097152KB +if [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 2097152 && "$ARCH" != "aarch64" && "$ARCH" != "arm" ]]; then # 2GB = 2097152KB echo -e "\nLess than 2GB of space available. Skipping disk test..." +elif [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 524288 && ("$ARCH" = "aarch64" || "$ARCH" = "arm") ]]; then # 512MB = 524288KB + echo -e "\nLess than 512MB of space available. Skipping disk test..." # if the skip disk flag was set, skip the disk performance test, otherwise test disk performance elif [ -z "$SKIP_FIO" ]; then # Perform ZFS filesystem detection and determine if we have enough free space according to spa_asize_inflation @@ -669,7 +697,9 @@ function launch_geekbench { GEEKBENCH_PATH=$YABS_PATH/geekbench_$VERSION mkdir -p $GEEKBENCH_PATH - if [[ $VERSION == *4* ]]; then # Geekbench v4 + if [[ $VERSION == *4* && ($ARCH = *aarch64* || $ARCH = *arm*) ]]; then + echo -e "\nARM architecture not supported by Geekbench 4, use Geekbench 5." + elif [[ $VERSION == *4* && $ARCH != *aarch64* && $ARCH != *arm* ]]; then # Geekbench v4 echo -en "\nRunning GB4 benchmark test... *cue elevator music*" # download the latest Geekbench 4 tarball and extract to geekbench temp directory curl -s https://cdn.geekbench.com/Geekbench-4.4.4-Linux.tar.gz | tar xz --strip-components=1 -C $GEEKBENCH_PATH &>/dev/null @@ -702,7 +732,11 @@ function launch_geekbench { else echo -en "\nRunning GB5 benchmark test... *cue elevator music*" # download the latest Geekbench 5 tarball and extract to geekbench temp directory - curl -s https://cdn.geekbench.com/Geekbench-5.4.1-Linux.tar.gz | tar xz --strip-components=1 -C $GEEKBENCH_PATH &>/dev/null + if [[ $ARCH = *aarch64* || $ARCH = *arm* ]]; then + curl -s https://cdn.geekbench.com/Geekbench-5.4.1-LinuxARMPreview.tar.gz | tar xz --strip-components=1 -C $GEEKBENCH_PATH &>/dev/null + else + curl -s https://cdn.geekbench.com/Geekbench-5.4.1-Linux.tar.gz | tar xz --strip-components=1 -C $GEEKBENCH_PATH &>/dev/null + fi # check if geekbench file exists if test -f "geekbench.license"; then