7 Commits

Author SHA1 Message Date
Mason Rowe
77af031702 update readme with recent additions (assessment tool and wiki) 2026-11-04 01:31:52 -05:00
Mason Rowe
21f62408ec add experimental RISC-V support (#97) 2026-10-31 01:41:45 -04:00
Mason Rowe
96f102f8d0 add riscv64 to fio/iperf3 binary build workflows (#97) 2026-10-31 00:56:40 -04:00
Mason Rowe
0e9a967115 fix for disk size over-counting with btrfs subvolumes/bind mounts (#130) 2026-10-30 21:37:42 -04:00
Mason Rowe
d83b3c7009 add tar check and clearer error message for geekbench (#99) 2026-10-30 21:13:54 -04:00
Mason Rowe
6a25c5bc6e update to latest geekbench release (v6.7.2; v7.1.0) 2026-10-07 22:42:29 -04:00
vpshostreview
14cf7fe435 Add VPS Host Review to the result submission sites (#133)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 23:33:42 -04:00
6 changed files with 145 additions and 36 deletions

View File

@@ -2,6 +2,11 @@ name: Build fio Static Binaries
on: on:
workflow_dispatch: workflow_dispatch:
inputs:
force:
description: 'Rebuild even if a release for the latest upstream version already exists (e.g. to add a new architecture)'
type: boolean
default: false
schedule: schedule:
# check upstream for a new fio release once a day # check upstream for a new fio release once a day
- cron: '23 5 * * *' - cron: '23 5 * * *'
@@ -36,8 +41,15 @@ jobs:
# Check if this version already exists in our releases (upstream tag is # Check if this version already exists in our releases (upstream tag is
# already prefixed, e.g. "fio-3.41", so it can be used as-is) # already prefixed, e.g. "fio-3.41", so it can be used as-is)
if gh release view "$VERSION" --repo ${{ github.repository }} >/dev/null 2>&1; then if gh release view "$VERSION" --repo ${{ github.repository }} >/dev/null 2>&1; then
# an existing release normally skips the build, but a manual dispatch with
# force=true rebuilds anyway (e.g. to add a new architecture to the assets)
if [ "${{ inputs.force }}" = "true" ]; then
echo "Version $VERSION already exists but force rebuild requested"
echo "should-build=true" >> $GITHUB_OUTPUT
else
echo "Version $VERSION already exists in releases" echo "Version $VERSION already exists in releases"
echo "should-build=false" >> $GITHUB_OUTPUT echo "should-build=false" >> $GITHUB_OUTPUT
fi
else else
echo "Version $VERSION does not exist, should build" echo "Version $VERSION does not exist, should build"
echo "should-build=true" >> $GITHUB_OUTPUT echo "should-build=true" >> $GITHUB_OUTPUT
@@ -65,6 +77,9 @@ jobs:
- arch: arm - arch: arm
cross: arm-linux-musleabihf cross: arm-linux-musleabihf
host: arm-linux-gnueabihf host: arm-linux-gnueabihf
- arch: riscv64
cross: riscv64-linux-musl
host: riscv64-linux-gnu
steps: steps:
- name: Create compilation script - name: Create compilation script
@@ -113,8 +128,9 @@ jobs:
# redefines struct prctl_mm_map under musl; sys/prctl.h alone is sufficient # redefines struct prctl_mm_map under musl; sys/prctl.h alone is sufficient
sed -i '/#include <linux\/prctl.h>/d' backend.c sed -i '/#include <linux\/prctl.h>/d' backend.c
CC=/root/$CROSS-cross/bin/$CROSS-gcc ./configure --disable-native --build-static CC=/root/$CROSS-cross/bin/$CROSS-gcc ./configure --disable-native --build-static
# link against libatomic for 32-bit/ARM targets that lack native 64-bit atomics # link against libatomic for 32-bit/ARM targets that lack native 64-bit atomics; -no-pie forces a
make EXTLIBS+=' -latomic' # classic static executable on default-PIE toolchains (riscv64), where a static-PIE fails to link
make EXTLIBS+=' -latomic -no-pie'
# verify no external shared library links # verify no external shared library links
libcheck fio libcheck fio
@@ -326,6 +342,7 @@ jobs:
- `fio_x86` - i686 (32-bit) - `fio_x86` - i686 (32-bit)
- `fio_aarch64` - ARM 64-bit - `fio_aarch64` - ARM 64-bit
- `fio_arm` - ARM 32-bit - `fio_arm` - ARM 32-bit
- `fio_riscv64` - RISC-V 64-bit
**Security Verification:** **Security Verification:**
All binaries have been scanned by VirusTotal and verified clean. All binaries have been scanned by VirusTotal and verified clean.

View File

@@ -2,6 +2,11 @@ name: Build iperf3 Static Binaries
on: on:
workflow_dispatch: workflow_dispatch:
inputs:
force:
description: 'Rebuild even if a release for the latest upstream version already exists (e.g. to add a new architecture)'
type: boolean
default: false
schedule: schedule:
# check upstream for a new iperf3 release once a day # check upstream for a new iperf3 release once a day
- cron: '47 5 * * *' - cron: '47 5 * * *'
@@ -35,8 +40,15 @@ jobs:
# Check if this version already exists in our releases # Check if this version already exists in our releases
if gh release view "iperf3-$VERSION" --repo ${{ github.repository }} >/dev/null 2>&1; then if gh release view "iperf3-$VERSION" --repo ${{ github.repository }} >/dev/null 2>&1; then
# an existing release normally skips the build, but a manual dispatch with
# force=true rebuilds anyway (e.g. to add a new architecture to the assets)
if [ "${{ inputs.force }}" = "true" ]; then
echo "Version $VERSION already exists but force rebuild requested"
echo "should-build=true" >> $GITHUB_OUTPUT
else
echo "Version $VERSION already exists in releases" echo "Version $VERSION already exists in releases"
echo "should-build=false" >> $GITHUB_OUTPUT echo "should-build=false" >> $GITHUB_OUTPUT
fi
else else
echo "Version $VERSION does not exist, should build" echo "Version $VERSION does not exist, should build"
echo "should-build=true" >> $GITHUB_OUTPUT echo "should-build=true" >> $GITHUB_OUTPUT
@@ -67,6 +79,9 @@ jobs:
- arch: arm - arch: arm
cross: arm-linux-musleabihf cross: arm-linux-musleabihf
host: arm-linux-gnueabihf host: arm-linux-gnueabihf
- arch: riscv64
cross: riscv64-linux-musl
host: riscv64-linux-gnu
steps: steps:
- name: Create compilation script - name: Create compilation script
@@ -104,7 +119,9 @@ jobs:
curl -L -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://github.com/esnet/iperf/archive/$VERSION.tar.gz" -o "iperf.tar.gz" curl -L -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://github.com/esnet/iperf/archive/$VERSION.tar.gz" -o "iperf.tar.gz"
tar xf iperf.tar.gz tar xf iperf.tar.gz
cd iperf-* 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 # -no-pie must be set via LDFLAGS at configure time (passing it to make overrides automake's LDFLAGS and
# drops --static); on default-PIE toolchains (riscv64) a static-PIE iperf3 links but segfaults at runtime
LDFLAGS="${LDFLAGS} -no-pie" 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
# remove libatomic.la so libtool links the static libatomic.a rather than # remove libatomic.la so libtool links the static libatomic.a rather than
# attempting to link libatomic.so into the static binary (breaks arm32 builds) # attempting to link libatomic.so into the static binary (breaks arm32 builds)
rm -f /root/$CROSS-cross/$CROSS/lib/libatomic.la rm -f /root/$CROSS-cross/$CROSS/lib/libatomic.la
@@ -349,6 +366,7 @@ jobs:
- `iperf3_x86` - i686 (32-bit) - `iperf3_x86` - i686 (32-bit)
- `iperf3_aarch64` - ARM 64-bit - `iperf3_aarch64` - ARM 64-bit
- `iperf3_arm` - ARM 32-bit (if available) - `iperf3_arm` - ARM 32-bit (if available)
- `iperf3_riscv64` - RISC-V 64-bit
${{ steps.check-arm.outputs.arm-note }} ${{ steps.check-arm.outputs.arm-note }}

View File

@@ -9,7 +9,12 @@ This script automates the execution of the best benchmarking tools in the indust
View Daily and Historical 📊 **[YABS Usage Stats Here](https://stats.yabs.sh/)** 📈 ([source](https://github.com/masonr/yabs-stats)). View Daily and Historical 📊 **[YABS Usage Stats Here](https://stats.yabs.sh/)** 📈 ([source](https://github.com/masonr/yabs-stats)).
Not sure what your numbers mean? 🔎 **[Paste your result for a rough assessment](https://stats.yabs.sh/assess)** — flags storage class, network port, CPU scaling and common gotchas, with links to the [wiki](https://github.com/masonr/yet-another-bench-script/wiki/Interpreting-Results). Runs entirely in your browser; nothing is uploaded.
### **What's New With YABS?** ### **What's New With YABS?**
* [04 Nov 2026](https://stats.yabs.sh/assess) - Paste YABS output at https://stats.yabs.sh/assess to get a quick and dirty assessment of disk, network and CPU results.
* [31 Oct 2026](https://github.com/masonr/yet-another-bench-script/wiki) - Launch of comprehensive [YABS wiki](https://github.com/masonr/yet-another-bench-script/wiki) covering topics from interpreting results, testing details, history, and more.
* [31 Oct 2026](https://github.com/masonr/yet-another-bench-script/issues/97) - Experimental RISC-V (riscv64) support added - fio/iperf3 static binaries and Geekbench 5/6/7 RISC-V preview builds are now supported.
* [19 Sep 2026](https://github.com/masonr/yet-another-bench-script/actions) - fio/iperf3 portable binary builds now automated via GitHub workflows. * [19 Sep 2026](https://github.com/masonr/yet-another-bench-script/actions) - fio/iperf3 portable binary builds now automated via GitHub workflows.
* [24 Jul 2026](https://github.com/masonr/yet-another-bench-script) - [Geekbench 7](https://www.geekbench.com/) is now available via the `-7` flag (Geekbench 6 remains the default). * [24 Jul 2026](https://github.com/masonr/yet-another-bench-script) - [Geekbench 7](https://www.geekbench.com/) is now available via the `-7` flag (Geekbench 6 remains the default).
* [04 Jul 2026](https://stats.yabs.sh/) - Check out YABS usage stats here -> https://stats.yabs.sh/ * [04 Jul 2026](https://stats.yabs.sh/) - Check out YABS usage stats here -> https://stats.yabs.sh/
@@ -28,7 +33,7 @@ wget -qO- yabs.sh | bash
**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. **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 compatibility has been introduced, however, is not considered entirely stable due to limited testing on distinct ARM devices. Report any errors or issues. **Experimental RISC-V Compatibility**: Initial RISC-V (riscv64) compatibility has been introduced, however, is not considered entirely stable due to limited testing on distinct RISC-V devices. Report any errors or issues.
**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). **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).
@@ -80,6 +85,7 @@ Sites supporting submission of YABS JSON results:
| [VPSBenchmarks](https://www.vpsbenchmarks.com/yabs/get_started) | `curl -sL yabs.sh \| bash -s -- -s https://www.vpsbenchmarks.com/yabs/upload` | | [VPSBenchmarks](https://www.vpsbenchmarks.com/yabs/get_started) | `curl -sL yabs.sh \| bash -s -- -s https://www.vpsbenchmarks.com/yabs/upload` |
| [serverlist.dev](https://serverlist.dev/) | `curl -sL yabs.sh \| bash -s -- -s "https://serverlist.dev/api/v1/yabs/submit"` | | [serverlist.dev](https://serverlist.dev/) | `curl -sL yabs.sh \| bash -s -- -s "https://serverlist.dev/api/v1/yabs/submit"` |
| [ServerVerify](https://serververify.com/benchmarks) | (sign up for account) | | [ServerVerify](https://serververify.com/benchmarks) | (sign up for account) |
| [VPS Host Review](https://vpshostreview.com/yabs) | `curl -sL yabs.sh \| bash -s -- -s "https://vpshostreview.com/yabs"` |
Example JSON output: [example.json](bin/example.json). Example JSON output: [example.json](bin/example.json).

View File

@@ -7,8 +7,8 @@ repository** - they are built automatically by GitHub Actions workflows
[build-iperf3.yml](../.github/workflows/build-iperf3.yml)) on GitHub-hosted [build-iperf3.yml](../.github/workflows/build-iperf3.yml)) on GitHub-hosted
runners and published as release assets on this repository: runners and published as release assets on this repository:
* `fio-*` releases (e.g. `fio-3.42`) - contain `fio_x64`, `fio_x86`, `fio_aarch64`, `fio_arm` * `fio-*` releases (e.g. `fio-3.42`) - contain `fio_x64`, `fio_x86`, `fio_aarch64`, `fio_arm`, `fio_riscv64`
* `iperf3-*` releases (e.g. `iperf3-3.21`) - contain `iperf3_x64`, `iperf3_x86`, `iperf3_aarch64`, `iperf3_arm` * `iperf3-*` releases (e.g. `iperf3-3.21`) - contain `iperf3_x64`, `iperf3_x86`, `iperf3_aarch64`, `iperf3_arm`, `iperf3_riscv64`
* `toolchains` release - musl cross-compilation toolchains mirrored from * `toolchains` release - musl cross-compilation toolchains mirrored from
[musl.cc](https://musl.cc/) (which blocks GitHub Actions IP ranges); see the [musl.cc](https://musl.cc/) (which blocks GitHub Actions IP ranges); see the
NOTICE.txt asset for licensing/source info NOTICE.txt asset for licensing/source info
@@ -33,7 +33,7 @@ issue if the binaries are out of date and lacking any security-related and/or
performance updates - the daily scheduled workflows should pick up new upstream performance updates - the daily scheduled workflows should pick up new upstream
releases automatically. releases automatically.
Note: ARM compatibility is considered experimental. Note: RISC-V compatibility is considered experimental.
### Compile Notes (manual builds) ### Compile Notes (manual builds)
@@ -57,6 +57,10 @@ Compilation of 32-bit and ARM-compatible binaries requires additional
environment variables to identify the proper musl toolchain and architecture to environment variables to identify the proper musl toolchain and architecture to
target for cross-compilation. target for cross-compilation.
The musl.cc riscv64 toolchain is default-PIE, so the scripts pass `-no-pie` to
produce classic static executables (a static-PIE fio fails to link, and a
static-PIE iperf3 links but segfaults at runtime).
**Compiling 32-bit x86 binaries**: **Compiling 32-bit x86 binaries**:
```sh ```sh
@@ -74,3 +78,9 @@ docker run -t -i --rm -v `pwd`:/io --env ARCH=aarch64 --env CROSS=aarch64-linux-
```sh ```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/cross-compile.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/cross-compile.sh
``` ```
**Compiling RISC-V 64-bit binaries**:
```sh
docker run -t -i --rm -v `pwd`:/io --env ARCH=riscv64 --env CROSS=riscv64-linux-musl --env HOST=riscv64-linux-gnu phusion/holy-build-box-64:latest bash /io/cross-compile.sh
```

View File

@@ -39,8 +39,9 @@ cd fio-fio-*
# conflicts under musl; sys/prctl.h alone is sufficient # conflicts under musl; sys/prctl.h alone is sufficient
sed -i '/#include <linux\/prctl.h>/d' backend.c sed -i '/#include <linux\/prctl.h>/d' backend.c
CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-native --build-static CC=/root/${CROSS}-cross/bin/${CROSS}-gcc ./configure --disable-native --build-static
# link against libatomic for 32-bit/ARM targets that lack native 64-bit atomics # link against libatomic for 32-bit/ARM targets that lack native 64-bit atomics; -no-pie forces a
make EXTLIBS+=' -latomic' # classic static executable on default-PIE toolchains (riscv64), where a static-PIE fails to link
make EXTLIBS+=' -latomic -no-pie'
# verify no external shared library links # verify no external shared library links
libcheck fio libcheck fio
@@ -52,7 +53,9 @@ cd ~
curl -L https://github.com/esnet/iperf/archive/3.21.tar.gz -o "iperf.tar.gz" curl -L https://github.com/esnet/iperf/archive/3.21.tar.gz -o "iperf.tar.gz"
tar xf iperf.tar.gz tar xf iperf.tar.gz
cd iperf-* 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 # -no-pie must be set via LDFLAGS at configure time (passing it to make overrides automake's LDFLAGS and
# drops --static); on default-PIE toolchains (riscv64) a static-PIE iperf3 links but segfaults at runtime
LDFLAGS="${LDFLAGS} -no-pie" 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
# remove libatomic.la so libtool links the static libatomic.a rather than # remove libatomic.la so libtool links the static libatomic.a rather than
# attempting to link libatomic.so into the static binary (breaks arm32 builds) # attempting to link libatomic.so into the static binary (breaks arm32 builds)
rm -f "/root/${CROSS}-cross/${CROSS}/lib/libatomic.la" rm -f "/root/${CROSS}-cross/${CROSS}/lib/libatomic.la"

95
yabs.sh
View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Yet Another Bench Script by Mason Rowe # Yet Another Bench Script by Mason Rowe
# Initial Oct 2019; Last update Sep 2026 # Initial Oct 2019; Last update Oct 2026
# Disclaimer: This project is a work in progress. Any errors or suggestions should be # Disclaimer: This project is a work in progress. Any errors or suggestions should be
# relayed to me via the GitHub project page linked below. # relayed to me via the GitHub project page linked below.
@@ -12,7 +12,7 @@
# performance via fio. The script is designed to not require any dependencies # performance via fio. The script is designed to not require any dependencies
# - either compiled or installed - nor admin privileges to run. # - either compiled or installed - nor admin privileges to run.
YABS_VERSION="v2026-09-20" YABS_VERSION="v2026-10-31"
echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #' echo -e '# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #'
echo -e '# Yet-Another-Bench-Script #' echo -e '# Yet-Another-Bench-Script #'
@@ -51,7 +51,10 @@ elif [[ $ARCH = *aarch* || $ARCH = *arm* ]]; then
# host is running an ARM 32-bit kernel # host is running an ARM 32-bit kernel
ARCH="arm" ARCH="arm"
fi fi
echo -e "\nARM compatibility is considered *experimental*" elif [[ $ARCH = *riscv64* ]]; then
# host is running a RISC-V 64-bit kernel
ARCH="riscv64"
echo -e "\nRISC-V compatibility is considered *experimental*"
else else
# host is running a non-supported kernel # host is running a non-supported kernel
echo -e "Architecture not supported by YABS." echo -e "Architecture not supported by YABS."
@@ -113,6 +116,12 @@ else
unset LOCAL_CURL unset LOCAL_CURL
fi fi
# check for tar (required to extract the Geekbench tarball)
if command -v tar >/dev/null 2>&1; then
LOCAL_TAR=true
else
unset LOCAL_TAR
fi
# test if the host has IPv4/IPv6 connectivity # test if the host has IPv4/IPv6 connectivity
[[ -n $LOCAL_CURL ]] && IP_CHECK_CMD="curl -s -m 4" || IP_CHECK_CMD="wget -qO- -T 4" [[ -n $LOCAL_CURL ]] && IP_CHECK_CMD="curl -s -m 4" || IP_CHECK_CMD="wget -qO- -T 4"
@@ -177,6 +186,8 @@ if [ -n "$PRINT_HELP" ]; then
([[ -z $LOCAL_IPERF ]] && echo -e " iperf3 not detected, will download precompiled binary") || ([[ -z $LOCAL_IPERF ]] && echo -e " iperf3 not detected, will download precompiled binary") ||
([[ -z $PREFER_BIN ]] && echo -e " iperf3 detected, using local package") || ([[ -z $PREFER_BIN ]] && echo -e " iperf3 detected, using local package") ||
echo -e " iperf3 detected, but using precompiled binary instead" echo -e " iperf3 detected, but using precompiled binary instead"
[[ -n $LOCAL_TAR ]] && echo -e " tar detected, required to extract geekbench" ||
echo -e " tar not detected, geekbench test will be skipped (install tar)"
echo -e echo -e
echo -e "Detected Connectivity:" echo -e "Detected Connectivity:"
[[ -n $IPV4_CHECK ]] && echo -e " IPv4 connected" || [[ -n $IPV4_CHECK ]] && echo -e " IPv4 connected" ||
@@ -260,13 +271,28 @@ if command -v lscpu >/dev/null 2>&1; then
else else
unset LOCAL_LSCPU unset LOCAL_LSCPU
fi fi
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ -n $LOCAL_LSCPU ]]; then if [[ $ARCH = *riscv64* ]]; then
# RISC-V /proc/cpuinfo lacks "model name"; try lscpu, the uarch field, the device tree, then fall back to the base ISA string
[[ -n $LOCAL_LSCPU ]] && CPU_PROC=$(lscpu | grep "Model name" | sed 's/Model name: *//g')
[[ -z $CPU_PROC ]] && CPU_PROC=$(awk -F: '/^uarch/ {print $2; exit}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
[[ -z $CPU_PROC && -r /proc/device-tree/model ]] && CPU_PROC=$(tr -d '\0' < /proc/device-tree/model)
[[ -z $CPU_PROC ]] && CPU_PROC="RISC-V"
CPU_ISA=$(awk -F: '/^isa/ {print $2; exit}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
[[ -n $CPU_ISA ]] && CPU_PROC="$CPU_PROC (${CPU_ISA%%_*})"
elif [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ -n $LOCAL_LSCPU ]]; then
CPU_PROC=$(lscpu | grep "Model name" | sed 's/Model name: *//g') CPU_PROC=$(lscpu | grep "Model name" | sed 's/Model name: *//g')
else else
CPU_PROC=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//') CPU_PROC=$(awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
fi fi
echo -e "Processor : $CPU_PROC" echo -e "Processor : $CPU_PROC"
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ -n $LOCAL_LSCPU ]]; then if [[ $ARCH = *riscv64* ]]; then
# RISC-V /proc/cpuinfo lacks "cpu MHz"; try lscpu then cpufreq sysfs
CPU_CORES=$(grep -c '^processor' /proc/cpuinfo)
[[ -n $LOCAL_LSCPU ]] && CPU_FREQ=$(lscpu | grep "CPU max MHz" | sed 's/CPU max MHz: *//g')
[[ -z $CPU_FREQ && -r /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq ]] && CPU_FREQ=$(awk '{ printf "%d", $1 / 1000 }' /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq)
[[ -z "$CPU_FREQ" ]] && CPU_FREQ="???"
CPU_FREQ="${CPU_FREQ} MHz"
elif [[ $ARCH = *aarch64* || $ARCH = *arm* ]] && [[ -n $LOCAL_LSCPU ]]; then
CPU_CORES=$(lscpu | grep "^[[:blank:]]*CPU(s):" | sed 's/CPU(s): *//g') CPU_CORES=$(lscpu | grep "^[[:blank:]]*CPU(s):" | sed 's/CPU(s): *//g')
CPU_FREQ=$(lscpu | grep "CPU max MHz" | sed 's/CPU max MHz: *//g') CPU_FREQ=$(lscpu | grep "CPU max MHz" | sed 's/CPU max MHz: *//g')
[[ -z "$CPU_FREQ" ]] && CPU_FREQ="???" [[ -z "$CPU_FREQ" ]] && CPU_FREQ="???"
@@ -276,10 +302,20 @@ else
CPU_FREQ=$(awk -F: ' /cpu MHz/ {freq=$2} END {print freq " MHz"}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//') CPU_FREQ=$(awk -F: ' /cpu MHz/ {freq=$2} END {print freq " MHz"}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//')
fi fi
echo -e "CPU cores : $CPU_CORES @ $CPU_FREQ" echo -e "CPU cores : $CPU_CORES @ $CPU_FREQ"
if [[ $ARCH = *riscv64* ]]; then
# RISC-V advertises capabilities in the ISA string: Zkn/Zknd/Zkne = scalar AES crypto extensions
CPU_AES=$(echo "$CPU_ISA" | grep -o -E '_zkn[de]?(_|$)')
else
CPU_AES=$(grep aes /proc/cpuinfo) CPU_AES=$(grep aes /proc/cpuinfo)
fi
[[ -z "$CPU_AES" ]] && CPU_AES="\xE2\x9D\x8C Disabled" || CPU_AES="\xE2\x9C\x94 Enabled" [[ -z "$CPU_AES" ]] && CPU_AES="\xE2\x9D\x8C Disabled" || CPU_AES="\xE2\x9C\x94 Enabled"
echo -e "AES-NI : $CPU_AES" echo -e "AES-NI : $CPU_AES"
if [[ $ARCH = *riscv64* ]]; then
# RISC-V: "h" in the base ISA letters = hypervisor extension
CPU_VIRT=$(echo "${CPU_ISA%%_*}" | grep 'h')
else
CPU_VIRT=$(grep 'vmx\|svm' /proc/cpuinfo) CPU_VIRT=$(grep 'vmx\|svm' /proc/cpuinfo)
fi
[[ -z "$CPU_VIRT" ]] && CPU_VIRT="\xE2\x9D\x8C Disabled" || CPU_VIRT="\xE2\x9C\x94 Enabled" [[ -z "$CPU_VIRT" ]] && CPU_VIRT="\xE2\x9D\x8C Disabled" || CPU_VIRT="\xE2\x9C\x94 Enabled"
echo -e "VM-x/AMD-V : $CPU_VIRT" echo -e "VM-x/AMD-V : $CPU_VIRT"
TOTAL_RAM_RAW=$(free | awk 'NR==2 {print $2}') TOTAL_RAM_RAW=$(free | awk 'NR==2 {print $2}')
@@ -288,8 +324,18 @@ echo -e "RAM : $TOTAL_RAM"
TOTAL_SWAP_RAW=$(free | grep Swap | awk '{ print $2 }') TOTAL_SWAP_RAW=$(free | grep Swap | awk '{ print $2 }')
TOTAL_SWAP=$(format_size "$TOTAL_SWAP_RAW") TOTAL_SWAP=$(format_size "$TOTAL_SWAP_RAW")
echo -e "Swap : $TOTAL_SWAP" echo -e "Swap : $TOTAL_SWAP"
# total disk size is calculated by adding all partitions of the types listed below (after the -t flags) # total disk size is calculated by adding all mounted filesystems of the types listed below, counting each
TOTAL_DISK_RAW=$(df -t simfs -t ext2 -t ext3 -t ext4 -t btrfs -t xfs -t vfat -t exfat -t ntfs -t swap --total 2>/dev/null | grep total | awk '{ print $2 }') # source device only once so filesystems mounted multiple times (e.g. btrfs subvolumes, bind mounts) are
# not double counted; only filtered mounts are stat'd so network mounts (nfs/cifs) are never touched
DISK_FS_TYPES="simfs ext2 ext3 ext4 btrfs xfs vfat exfat ntfs swap"
TOTAL_DISK_RAW=$(while read -r FS_SRC FS_MNT FS_TYPE _; do
case " $DISK_FS_TYPES " in *" $FS_TYPE "*)
# mount points are octal-escaped in /proc/mounts (e.g. "\040" for spaces), decode before use
echo "$FS_SRC $(stat -f -c '%b %S' "$(printf '%b' "$FS_MNT")" 2>/dev/null)" ;;
esac
done 2>/dev/null < /proc/mounts | awk 'NF == 3 && !seen[$1]++ { total += $2 * $3 / 1024 } END { if (total > 0) printf "%d\n", total }')
# fall back to the df-based calculation if the above produced nothing (e.g. stat or /proc/mounts unavailable)
[[ -z $TOTAL_DISK_RAW ]] && TOTAL_DISK_RAW=$(df -t simfs -t ext2 -t ext3 -t ext4 -t btrfs -t xfs -t vfat -t exfat -t ntfs -t swap --total 2>/dev/null | grep total | awk '{ print $2 }')
TOTAL_DISK=$(format_size "$TOTAL_DISK_RAW") TOTAL_DISK=$(format_size "$TOTAL_DISK_RAW")
echo -e "Disk : $TOTAL_DISK" echo -e "Disk : $TOTAL_DISK"
DISTRO=$(grep 'PRETTY_NAME' /etc/os-release | cut -d '"' -f 2 ) DISTRO=$(grep 'PRETTY_NAME' /etc/os-release | cut -d '"' -f 2 )
@@ -474,7 +520,7 @@ function format_iops {
# Parameters: # Parameters:
# - (none) # - (none)
function disk_test { function disk_test {
if [[ "$ARCH" = "aarch64" || "$ARCH" = "arm" ]]; then if [[ "$ARCH" = "aarch64" || "$ARCH" = "arm" || "$ARCH" = "riscv64" ]]; then
FIO_SIZE=512M FIO_SIZE=512M
else else
FIO_SIZE=2G FIO_SIZE=2G
@@ -551,9 +597,9 @@ function dd_test {
# check if disk performance is being tested and the host has required space (2G) # check if disk performance is being tested and the host has required space (2G)
AVAIL_SPACE=$(df -k . | awk 'NR==2{print $4}') AVAIL_SPACE=$(df -k . | awk 'NR==2{print $4}')
if [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 2097152 && "$ARCH" != "aarch64" && "$ARCH" != "arm" ]]; then # 2GB = 2097152KB if [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 2097152 && "$ARCH" != "aarch64" && "$ARCH" != "arm" && "$ARCH" != "riscv64" ]]; then # 2GB = 2097152KB
echo -e "\nLess than 2GB of space available. Skipping disk test..." 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 elif [[ -z "$SKIP_FIO" && "$AVAIL_SPACE" -lt 524288 && ("$ARCH" = "aarch64" || "$ARCH" = "arm" || "$ARCH" = "riscv64") ]]; then # 512MB = 524288KB
echo -e "\nLess than 512MB of space available. Skipping disk test..." 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 # if the skip disk flag was set, skip the disk performance test, otherwise test disk performance
elif [ -z "$SKIP_FIO" ]; then elif [ -z "$SKIP_FIO" ]; then
@@ -974,9 +1020,9 @@ function launch_geekbench {
# check for curl vs wget # check for curl vs wget
[[ -n $LOCAL_CURL ]] && DL_CMD="curl -s" || DL_CMD="wget -qO-" [[ -n $LOCAL_CURL ]] && DL_CMD="curl -s" || DL_CMD="wget -qO-"
if [[ $VERSION == *4* && ($ARCH = *aarch64* || $ARCH = *arm*) ]]; then if [[ $VERSION == *4* && ($ARCH = *aarch64* || $ARCH = *arm* || $ARCH = *riscv64*) ]]; then
echo -e "\nARM architecture not supported by Geekbench 4, use Geekbench 5 or 6." echo -e "\nARM/RISC-V architectures not supported by Geekbench 4, use Geekbench 5 or 6."
elif [[ $VERSION == *4* && $ARCH != *aarch64* && $ARCH != *arm* ]]; then # Geekbench v4 elif [[ $VERSION == *4* && $ARCH != *aarch64* && $ARCH != *arm* && $ARCH != *riscv64* ]]; then # Geekbench v4
GB_URL="https://cdn.geekbench.com/Geekbench-4.4.4-Linux.tar.gz" GB_URL="https://cdn.geekbench.com/Geekbench-4.4.4-Linux.tar.gz"
[[ "$ARCH" == *"x86"* ]] && GB_CMD="geekbench_x86_32" || GB_CMD="geekbench4" [[ "$ARCH" == *"x86"* ]] && GB_CMD="geekbench_x86_32" || GB_CMD="geekbench4"
GB_RUN="True" GB_RUN="True"
@@ -988,23 +1034,32 @@ function launch_geekbench {
echo -e "\nGeekbench $VERSION cannot run on 32-bit architectures. Skipping test." echo -e "\nGeekbench $VERSION cannot run on 32-bit architectures. Skipping test."
else else
if [[ $VERSION == *5* ]]; then # Geekbench v5 if [[ $VERSION == *5* ]]; then # Geekbench v5
[[ $ARCH = *aarch64* || $ARCH = *arm* ]] && GB_URL="https://cdn.geekbench.com/Geekbench-5.5.1-LinuxARMPreview.tar.gz" \ GB_VER="5.5.1"
|| GB_URL="https://cdn.geekbench.com/Geekbench-5.5.1-Linux.tar.gz"
GB_CMD="geekbench5" GB_CMD="geekbench5"
elif [[ $VERSION == *6* ]]; then # Geekbench v6 elif [[ $VERSION == *6* ]]; then # Geekbench v6
[[ $ARCH = *aarch64* || $ARCH = *arm* ]] && GB_URL="https://cdn.geekbench.com/Geekbench-6.7.1-LinuxARMPreview.tar.gz" \ GB_VER="6.7.2"
|| GB_URL="https://cdn.geekbench.com/Geekbench-6.7.1-Linux.tar.gz"
GB_CMD="geekbench6" GB_CMD="geekbench6"
else # Geekbench v7 else # Geekbench v7
[[ $ARCH = *aarch64* || $ARCH = *arm* ]] && GB_URL="https://cdn.geekbench.com/Geekbench-7.0.0-LinuxARMPreview.tar.gz" \ GB_VER="7.1.0"
|| GB_URL="https://cdn.geekbench.com/Geekbench-7.0.0-Linux.tar.gz"
GB_CMD="geekbench7" GB_CMD="geekbench7"
fi fi
# select the Geekbench build for the host architecture (ARM and RISC-V builds are "Preview" releases)
if [[ $ARCH = *aarch64* || $ARCH = *arm* ]]; then
GB_URL="https://cdn.geekbench.com/Geekbench-$GB_VER-LinuxARMPreview.tar.gz"
elif [[ $ARCH = *riscv64* ]]; then
GB_URL="https://cdn.geekbench.com/Geekbench-$GB_VER-LinuxRISCVPreview.tar.gz"
else
GB_URL="https://cdn.geekbench.com/Geekbench-$GB_VER-Linux.tar.gz"
fi
GB_RUN="True" GB_RUN="True"
fi fi
fi fi
if [[ $GB_RUN == *True* ]]; then # run GB test if [[ $GB_RUN == *True* ]] && [[ -z $LOCAL_TAR ]] && ! command -v "$GB_CMD" &>/dev/null; then
# tar is needed to extract the downloaded Geekbench tarball (missing on e.g. AlmaLinux 9 minimal)
echo -e "\nGeekbench $VERSION requires tar to extract the download, but tar was not found."
echo -e "Install tar (e.g. 'dnf install tar' or 'apt install tar') and re-run. Skipping Geekbench $VERSION."
elif [[ $GB_RUN == *True* ]]; then # run GB test
echo -en "\nRunning GB$VERSION benchmark test... *cue elevator music*" echo -en "\nRunning GB$VERSION benchmark test... *cue elevator music*"
# check for local geekbench installed # check for local geekbench installed