11 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
Mason Rowe
316260707a fix formatting issue 2026-09-20 00:27:26 -04:00
Mason Rowe
ad1af039ce pull fio/iperf3 binaries from github releases instead of repo 2026-09-20 00:26:00 -04:00
Mason Rowe
7d27d65cb3 update binary workflows to poll virustotal for scan completion 2026-09-19 21:42:37 -04:00
Mason Rowe
e29813716c update binary workflows to grab github-hosted toolchain assets 2026-09-19 21:25:18 -04:00
15 changed files with 272 additions and 100 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
@@ -86,9 +101,12 @@ jobs:
yum install -y yum-plugin-ovl # fix for docker overlay fs yum install -y yum-plugin-ovl # fix for docker overlay fs
yum install -y xz yum install -y xz
# download musl cross compilation toolchain # download musl cross compilation toolchain - mirrored as a release asset on
# this repo since musl.cc blocks GitHub Actions IP ranges (musl.cc fallback
# kept for local runs)
cd ~ cd ~
curl -L -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://musl.cc/$CROSS-cross.tgz" -o "$CROSS-cross.tgz" curl -fL -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://github.com/masonr/yet-another-bench-script/releases/download/toolchains/$CROSS-cross.tgz" -o "$CROSS-cross.tgz" \
|| curl -fL -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://musl.cc/$CROSS-cross.tgz" -o "$CROSS-cross.tgz"
tar xf "$CROSS-cross.tgz" tar xf "$CROSS-cross.tgz"
# download, compile, and install libaio as static library # download, compile, and install libaio as static library
@@ -110,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
@@ -192,18 +211,20 @@ jobs:
echo "${filename}:${analysis_id}" >> analysis_ids.txt echo "${filename}:${analysis_id}" >> analysis_ids.txt
done done
# Wait 2 minutes for scans to complete
echo "Waiting 2 minutes for VirusTotal scans to complete..."
sleep 120
- name: Retrieve VirusTotal scan results - name: Retrieve VirusTotal scan results
id: get-results id: get-results
run: | run: |
ALL_CLEAN=true ALL_CLEAN=true
# Poll each analysis until it completes; VirusTotal scans can take a few
# minutes after upload, so allow up to ~5 minutes per binary (10 polls,
# 30s apart) before giving up. Files are processed sequentially, so by
# the time the first completes the rest are usually already done.
while IFS=':' read -r filename analysis_id; do while IFS=':' read -r filename analysis_id; do
echo "Retrieving results for $filename (ID: $analysis_id)..." echo "Retrieving results for $filename (ID: $analysis_id)..."
status="queued"
for ((attempts=1; attempts<=10; attempts++)); do
# Get scan results # Get scan results
result_response=$(curl -4 --retry 5 --retry-delay 2 --connect-timeout 15 -s --request GET \ result_response=$(curl -4 --retry 5 --retry-delay 2 --connect-timeout 15 -s --request GET \
--url "https://www.virustotal.com/api/v3/analyses/$analysis_id" \ --url "https://www.virustotal.com/api/v3/analyses/$analysis_id" \
@@ -211,6 +232,10 @@ jobs:
--header "x-apikey: ${{ secrets.VIRUSTOTAL_API_KEY }}") --header "x-apikey: ${{ secrets.VIRUSTOTAL_API_KEY }}")
status=$(echo "$result_response" | jq -r '.data.attributes.status // "unknown"') status=$(echo "$result_response" | jq -r '.data.attributes.status // "unknown"')
[ "$status" = "completed" ] && break
echo "$filename still scanning (attempt $attempts of 10), waiting 30s..."
sleep 30
done
if [ "$status" = "completed" ]; then if [ "$status" = "completed" ]; then
malicious=$(echo "$result_response" | jq -r '.data.attributes.stats.malicious // 0') malicious=$(echo "$result_response" | jq -r '.data.attributes.stats.malicious // 0')
@@ -232,7 +257,7 @@ jobs:
echo "| $filename | $status_text | $malicious | $suspicious | $undetected | [$file_hash]($vt_url) |" >> scan_results.md echo "| $filename | $status_text | $malicious | $suspicious | $undetected | [$file_hash]($vt_url) |" >> scan_results.md
else else
echo "| $filename | ⏳ Pending | N/A | N/A | N/A | Scan not completed |" >> scan_results.md echo "| $filename | ⏳ Timed out | N/A | N/A | N/A | Scan did not complete in ~5 min |" >> scan_results.md
ALL_CLEAN=false ALL_CLEAN=false
fi fi
@@ -317,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
@@ -88,9 +103,12 @@ jobs:
yum install -y yum-plugin-ovl # fix for docker overlay fs yum install -y yum-plugin-ovl # fix for docker overlay fs
yum install -y xz yum install -y xz
# download musl cross compilation toolchain # download musl cross compilation toolchain - mirrored as a release asset on
# this repo since musl.cc blocks GitHub Actions IP ranges (musl.cc fallback
# kept for local runs)
cd ~ cd ~
curl -L -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://musl.cc/$CROSS-cross.tgz" -o "$CROSS-cross.tgz" curl -fL -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://github.com/masonr/yet-another-bench-script/releases/download/toolchains/$CROSS-cross.tgz" -o "$CROSS-cross.tgz" \
|| curl -fL -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://musl.cc/$CROSS-cross.tgz" -o "$CROSS-cross.tgz"
tar xf "$CROSS-cross.tgz" tar xf "$CROSS-cross.tgz"
# Activate Holy Build Box exe compilation environment # Activate Holy Build Box exe compilation environment
@@ -101,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
@@ -193,18 +213,20 @@ jobs:
echo "${filename}:${analysis_id}" >> analysis_ids.txt echo "${filename}:${analysis_id}" >> analysis_ids.txt
done done
# Wait 2 minutes for scans to complete
echo "Waiting 2 minutes for VirusTotal scans to complete..."
sleep 120
- name: Retrieve VirusTotal scan results - name: Retrieve VirusTotal scan results
id: get-results id: get-results
run: | run: |
ALL_CLEAN=true ALL_CLEAN=true
# Poll each analysis until it completes; VirusTotal scans can take a few
# minutes after upload, so allow up to ~5 minutes per binary (10 polls,
# 30s apart) before giving up. Files are processed sequentially, so by
# the time the first completes the rest are usually already done.
while IFS=':' read -r filename analysis_id; do while IFS=':' read -r filename analysis_id; do
echo "Retrieving results for $filename (ID: $analysis_id)..." echo "Retrieving results for $filename (ID: $analysis_id)..."
status="queued"
for ((attempts=1; attempts<=10; attempts++)); do
# Get scan results # Get scan results
result_response=$(curl -4 --retry 5 --retry-delay 2 --connect-timeout 15 -s --request GET \ result_response=$(curl -4 --retry 5 --retry-delay 2 --connect-timeout 15 -s --request GET \
--url "https://www.virustotal.com/api/v3/analyses/$analysis_id" \ --url "https://www.virustotal.com/api/v3/analyses/$analysis_id" \
@@ -212,6 +234,10 @@ jobs:
--header "x-apikey: ${{ secrets.VIRUSTOTAL_API_KEY }}") --header "x-apikey: ${{ secrets.VIRUSTOTAL_API_KEY }}")
status=$(echo "$result_response" | jq -r '.data.attributes.status // "unknown"') status=$(echo "$result_response" | jq -r '.data.attributes.status // "unknown"')
[ "$status" = "completed" ] && break
echo "$filename still scanning (attempt $attempts of 10), waiting 30s..."
sleep 30
done
if [ "$status" = "completed" ]; then if [ "$status" = "completed" ]; then
malicious=$(echo "$result_response" | jq -r '.data.attributes.stats.malicious // 0') malicious=$(echo "$result_response" | jq -r '.data.attributes.stats.malicious // 0')
@@ -233,7 +259,7 @@ jobs:
echo "| $filename | $status_text | $malicious | $suspicious | $undetected | [$file_hash]($vt_url) |" >> scan_results.md echo "| $filename | $status_text | $malicious | $suspicious | $undetected | [$file_hash]($vt_url) |" >> scan_results.md
else else
echo "| $filename | ⏳ Pending | N/A | N/A | N/A | Scan not completed |" >> scan_results.md echo "| $filename | ⏳ Timed out | N/A | N/A | N/A | Scan did not complete in ~5 min |" >> scan_results.md
ALL_CLEAN=false ALL_CLEAN=false
fi fi
@@ -340,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,11 +9,15 @@ 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.
* [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/
* [27 Feb 2023](https://github.com/masonr/yet-another-bench-script/commit/06eaa2ab3b32355bec8278c51c4be93b3662a96d) - Newly released [Geekbench 6](https://www.geekbench.com/) is added as the default Geekbench test.
* [26 Feb 2023](https://github.com/masonr/yet-another-bench-script/commit/f075baf59c3057983fff0a30ea0c746b5ea88d91) - Network information added to YABS output using [ip-api](https://ip-api.com/).
## How to Run ## How to Run
@@ -29,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).
@@ -79,7 +83,9 @@ Sites supporting submission of YABS JSON results:
| --- | --- | | --- | --- |
| [YABSdb](https://yabsdb.com/) | `curl -sL yabs.sh \| bash -s -- -s "https://yabsdb.com/add"` | | [YABSdb](https://yabsdb.com/) | `curl -sL yabs.sh \| bash -s -- -s "https://yabsdb.com/add"` |
| [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"` |
| [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).
@@ -91,7 +97,7 @@ Example JSON output: [example.json](bin/example.json).
### Security Notice ### Security Notice
This script relies on external binaries in order to complete the performance tests. The network (iperf3) and disk (fio) tests use binaries that are compiled by myself utilizing a [Holy Build Box](https://github.com/phusion/holy-build-box) compilation environment to ensure binary portability. The reasons for doing this include ensuring standardized (parsable) output, allowing support of both 32-bit and 64-bit architectures, bypassing the need for prerequisites to be compiled and/or installed, among other reasons. For the system test, a Geekbench tarball is downloaded, extracted, and the resulting binary is run. Use this script at your own risk as you would with any script publicly available on the net. Additional information regarding the binaries, including compilation notes and steps, can be found in the bin directory's [README page](bin/README.md). This script relies on external binaries in order to complete the performance tests. The network (iperf3) and disk (fio) tests use binaries that are built by GitHub Actions workflows in a [Holy Build Box](https://github.com/phusion/holy-build-box) compilation environment to ensure binary portability, and are published as release assets on this repository (scanned via VirusTotal with SHA-256 checksums included). The reasons for using pre-compiled binaries include ensuring standardized (parsable) output, allowing support of both 32-bit and 64-bit architectures, bypassing the need for prerequisites to be compiled and/or installed, among other reasons. For the system test, a Geekbench tarball is downloaded, extracted, and the resulting binary is run. Use this script at your own risk as you would with any script publicly available on the net. Additional information regarding the binaries, including compilation notes and steps, can be found in the bin directory's [README page](bin/README.md).
## Example Output ## Example Output

View File

@@ -1,28 +1,49 @@
## YABS Pre-Compiled Binaries ## YABS Pre-Compiled Binaries
This directory contains all of the binaries required to run the benchmarking tests. Naturally, there is a security risk to your machine and its contents by running this script since, after all, this is just a script on the internet. You'll simply have to have confidence that I don't have malicious intent and am semi-competent at writing a bash script. The script is made public so you can look at the code yourself. The binaries were compiled using a [Holy Build Box](https://github.com/phusion/holy-build-box) compilation environment in order to ensure the most portability. The compiled binary version numbers and compilations steps are noted below. Please open an issue if the compiled version is out of date and lacking any security-related and/or performance updates. This directory contains the compilation scripts used to build the fio and iperf3
binaries that YABS uses. **The binaries themselves are no longer committed to the
repository** - they are built automatically by GitHub Actions workflows
([build-fio.yml](../.github/workflows/build-fio.yml) and
[build-iperf3.yml](../.github/workflows/build-iperf3.yml)) on GitHub-hosted
runners and published as release assets on this repository:
### Binaries * `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_riscv64`
* `toolchains` release - musl cross-compilation toolchains mirrored from
[musl.cc](https://musl.cc/) (which blocks GitHub Actions IP ranges); see the
NOTICE.txt asset for licensing/source info
| Binary Name | Version | Compile Date | Architecture | OS | SHA-256 Hash<br>(VirusTotal Scan) | Each binary release includes SHA-256 checksums (`*-checksums.sha256`), a
|:-:|:-:|:-:|:-:|:-:|:-:| VirusTotal scan summary in the release notes, and the exact upstream source
| fio_x64 | 3.39 | 20-APR-2025 | x86_64 | 64-bit | [b511bda](https://www.virustotal.com/gui/file/b511bda3b26b6d840698f543d63e956d7466b8512c10ff0ada8292d556c33fb1) | tarball the binaries were built from. Binaries are cross-compiled with musl
| fio_x86 | 3.39 | 20-APR-2025 | i686 | 32-bit | [42e2e0b](https://www.virustotal.com/gui/file/42e2e0b0370faeb8e53dcf48dfff15daa9baaadfd196d9bdda57af196bedf0b3) | toolchains for maximum portability.
| fio_aarch64 | 3.39 | 20-APR-2025 | ARM (aarch64) | 64-bit | [e2942a2](https://www.virustotal.com/gui/file/e2942a26d4b249076486677c9c12cd7f1a572854a5e136597d1391e8ad75ffb0) |
| fio_arm | 3.39 | 20-APR-2025 | ARM | 32-bit | [3a96b1c](https://www.virustotal.com/gui/file/3a96b1cadfb51501b7fd54dc47a4dad666dc4382d4fe152116c62ae6a07485ea) |
| iperf3_x64 | 3.18 | 14-DEC-2024 | x86_64 | 64-bit | [ef787ab](https://www.virustotal.com/gui/file/ef787abbe4b09c7958ed592df52dfe3a2848cbdee5b76738c757d7c51c348053) |
| iperf3_x86 | 3.18 | 14-DEC-2024 | i686 | 32-bit | [655eb51](https://www.virustotal.com/gui/file/655eb51abc36ddaa624c1d0e98c6930e8b1e9d91c85e5a3443624355656be9b9) |
| iperf3_aarch64 | 3.18 | 14-DEC-2024 | ARM (aarch64) | 64-bit | [92e5821](https://www.virustotal.com/gui/file/92e5821cfbaa1f8faf123b4d6773dc0f6efef221b9308668a21ddabc04a1de20) |
| iperf3_arm | 3.15* | 20-OCT-2023 | ARM | 32-bit | [310e80f](https://www.virustotal.com/gui/file/310e80f442dda47fa0fe41225af85e8b91e75116dce5187f123380fd3c3c85a8) |
Note: ARM compatibility is considered experimental. Static binaries for 32-bit and ARM-based machines are cross-compiled within a Holy Build Box container using the [musl toolchain](https://musl.cc/). At runtime, yabs.sh auto-detects the latest `fio-*`/`iperf3-*` release via the
repository's releases feed and downloads the appropriate binary for the host
architecture. If the lookup fails, it falls back to a pinned release tag.
### Compile Notes Naturally, there is a security risk to your machine and its contents by running
this script since, after all, this is just a script on the internet. You'll
simply have to have confidence that I don't have malicious intent and am
semi-competent at writing a bash script. The script and the workflows that build
the binaries are public so you can look at the code yourself. The binaries are
compiled using a [Holy Build Box](https://github.com/phusion/holy-build-box)
compilation environment in order to ensure the most portability. Please open an
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
releases automatically.
Note: RISC-V compatibility is considered experimental.
### Compile Notes (manual builds)
The workflows above are the canonical build path. To build manually, the same
scripts can be run inside a Holy Build Box container:
**Pre-reqs**: **Pre-reqs**:
* Docker - https://www.docker.com/ * Docker - https://www.docker.com/
**Compiling 64-bit binaries**: **Compiling 64-bit (x86_64) binaries**:
```sh ```sh
docker run -t -i --rm -v `pwd`:/io phusion/holy-build-box-64:latest bash /io/compile.sh docker run -t -i --rm -v `pwd`:/io phusion/holy-build-box-64:latest bash /io/compile.sh
@@ -32,9 +53,15 @@ docker run -t -i --rm -v `pwd`:/io phusion/holy-build-box-64:latest bash /io/com
### Cross-compiling Notes ### Cross-compiling Notes
Compilation of ARM-compatible binaries requires additional environment variables to identify the proper musl toolchain and architecture to target for cross-compilation. Compilation of 32-bit and ARM-compatible binaries requires additional
environment variables to identify the proper musl toolchain and architecture to
target for cross-compilation.
**Compiling 32-bit binaries**: 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**:
```sh ```sh
docker run -t -i --rm -v `pwd`:/io --env ARCH=x86 --env CROSS=i686-linux-musl --env HOST=i686-linux-musl phusion/holy-build-box-64:latest bash /io/cross-compile.sh docker run -t -i --rm -v `pwd`:/io --env ARCH=x86 --env CROSS=i686-linux-musl --env HOST=i686-linux-musl phusion/holy-build-box-64:latest bash /io/cross-compile.sh
@@ -46,12 +73,14 @@ docker run -t -i --rm -v `pwd`:/io --env ARCH=x86 --env CROSS=i686-linux-musl --
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/cross-compile.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/cross-compile.sh
``` ```
**Compiling ARM 32-bit binaries\***: **Compiling ARM 32-bit binaries**:
```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
``` ```
64-bit (aarch64) and 32-bit (x86, arm) binaries will be placed in the current directory. **Compiling RISC-V 64-bit binaries**:
\* ARM 32-bit: Last sucessful compiliation of ARM 32-bit binary for iperf3 is v3.15. All later versions fail to compile. ```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

@@ -36,9 +36,12 @@ source /hbb_exe/activate
# download and compile fio # download and compile fio
cd ~ cd ~
curl -L https://github.com/axboe/fio/archive/fio-3.39.tar.gz -o "fio.tar.gz" curl -L https://github.com/axboe/fio/archive/fio-3.42.tar.gz -o "fio.tar.gz"
tar xf fio.tar.gz tar xf fio.tar.gz
cd fio-fio* cd fio-fio-*
# fio >= 3.42 includes both linux/prctl.h and sys/prctl.h in backend.c, which
# conflicts under musl; sys/prctl.h alone is sufficient (harmless on glibc too)
sed -i '/#include <linux\/prctl.h>/d' backend.c
./configure --disable-native ./configure --disable-native
make make
@@ -49,9 +52,9 @@ cp fio "/io/fio_$ARCH"
# download and compile iperf # download and compile iperf
cd ~ cd ~
curl -L https://github.com/esnet/iperf/archive/3.18.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-*
./configure --disable-shared --disable-profiling ./configure --disable-shared --disable-profiling
make make

View File

@@ -8,14 +8,16 @@ set -x
# remove obsolete CentOS repos # remove obsolete CentOS repos
cd /etc/yum.repos.d/ cd /etc/yum.repos.d/
rm CentOS-Base.repo CentOS-SCLo-scl-rh.repo CentOS-SCLo-scl.repo CentOS-fasttrack.repo CentOS-x86_64-kernel.repo rm -f CentOS-Base.repo CentOS-SCLo-scl-rh.repo CentOS-SCLo-scl.repo CentOS-fasttrack.repo CentOS-x86_64-kernel.repo
yum install -y yum-plugin-ovl # fix for docker overlay fs yum install -y yum-plugin-ovl # fix for docker overlay fs
yum install -y xz yum install -y xz
# download musl cross compilation toolchain # download musl cross compilation toolchain - mirrored as a release asset on the
# repo since musl.cc blocks GitHub Actions IP ranges (musl.cc fallback kept)
cd ~ cd ~
curl -L "https://musl.cc/${CROSS}-cross.tgz" -o "${CROSS}-cross.tgz" curl -fL -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://github.com/masonr/yet-another-bench-script/releases/download/toolchains/${CROSS}-cross.tgz" -o "${CROSS}-cross.tgz" \
|| curl -fL -4 --retry 5 --retry-delay 2 --connect-timeout 15 "https://musl.cc/${CROSS}-cross.tgz" -o "${CROSS}-cross.tgz"
tar xf "${CROSS}-cross.tgz" tar xf "${CROSS}-cross.tgz"
# download, compile, and install libaio as static library # download, compile, and install libaio as static library
@@ -30,11 +32,16 @@ source /hbb_exe/activate
# download and compile fio # download and compile fio
cd ~ cd ~
curl -L https://github.com/axboe/fio/archive/fio-3.39.tar.gz -o "fio.tar.gz" curl -L https://github.com/axboe/fio/archive/fio-3.42.tar.gz -o "fio.tar.gz"
tar xf fio.tar.gz tar xf fio.tar.gz
cd fio-fio* cd fio-fio-*
# fio >= 3.42 includes both linux/prctl.h and sys/prctl.h in backend.c, which
# conflicts under musl; sys/prctl.h alone is sufficient
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
make # link against libatomic for 32-bit/ARM targets that lack native 64-bit atomics; -no-pie forces a
# 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
@@ -43,10 +50,15 @@ cp fio "/io/fio_$ARCH"
# download and compile iperf # download and compile iperf
cd ~ cd ~
curl -L https://github.com/esnet/iperf/archive/3.18.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
# attempting to link libatomic.so into the static binary (breaks arm32 builds)
rm -f "/root/${CROSS}-cross/${CROSS}/lib/libatomic.la"
make make
# verify no external shared library links # verify no external shared library links

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

125
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-17" 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" ||
@@ -195,6 +206,20 @@ if [ -n "$PRINT_HELP" ]; then
exit 0 exit 0
fi fi
# determine which repo release tags to pull the precompiled fio/iperf3 binaries from:
# auto-detect the latest matching releases from the repo's releases feed and fall
# back to the pinned tags below if the lookup fails
FIO_BIN_TAG="fio-3.42" # pinned fallback fio release
IPERF_BIN_TAG="iperf3-3.21" # pinned fallback iperf3 release
if [[ -z $SKIP_FIO || -z $SKIP_IPERF ]]; then
BIN_RELEASES_FEED=$($IP_CHECK_CMD https://github.com/masonr/yet-another-bench-script/releases.atom 2>/dev/null)
FIO_BIN_TAG_LATEST=$(echo "$BIN_RELEASES_FEED" | grep -oE 'fio-[0-9]+\.[0-9]+' | head -n 1)
IPERF_BIN_TAG_LATEST=$(echo "$BIN_RELEASES_FEED" | grep -oE 'iperf3-[0-9]+\.[0-9]+' | head -n 1)
[[ -n $FIO_BIN_TAG_LATEST ]] && FIO_BIN_TAG=$FIO_BIN_TAG_LATEST
[[ -n $IPERF_BIN_TAG_LATEST ]] && IPERF_BIN_TAG=$IPERF_BIN_TAG_LATEST
unset FIO_BIN_TAG_LATEST IPERF_BIN_TAG_LATEST BIN_RELEASES_FEED
fi
# format_size # format_size
# Purpose: Formats raw disk and memory sizes from kibibytes (KiB) to largest unit # Purpose: Formats raw disk and memory sizes from kibibytes (KiB) to largest unit
# Parameters: # Parameters:
@@ -246,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="???"
@@ -262,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}')
@@ -274,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 )
@@ -460,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
@@ -537,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
@@ -646,14 +706,14 @@ fi
if [[ -z "$PREFER_BIN" && -n "$LOCAL_FIO" ]]; then # local fio has been detected, use instead of pre-compiled binary if [[ -z "$PREFER_BIN" && -n "$LOCAL_FIO" ]]; then # local fio has been detected, use instead of pre-compiled binary
FIO_CMD=fio FIO_CMD=fio
else else
# download fio binary # download fio binary from the binary release on the repo
if [[ -n $LOCAL_CURL ]]; then if [[ -n $LOCAL_CURL ]]; then
curl -s --connect-timeout 5 --retry 5 --retry-delay 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/fio/fio_$ARCH -o "$DISK_PATH/fio" curl -sfL --connect-timeout 5 --retry 5 --retry-delay 0 "https://github.com/masonr/yet-another-bench-script/releases/download/$FIO_BIN_TAG/fio_$ARCH" -o "$DISK_PATH/fio"
else else
wget -q -T 5 -t 5 -w 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/fio/fio_$ARCH -O "$DISK_PATH/fio" wget -q -T 5 -t 5 -w 0 "https://github.com/masonr/yet-another-bench-script/releases/download/$FIO_BIN_TAG/fio_$ARCH" -O "$DISK_PATH/fio"
fi fi
if [ ! -f "$DISK_PATH/fio" ]; then # ensure fio binary download successfully if [ ! -s "$DISK_PATH/fio" ]; then # ensure fio binary download successfully
echo -en "\r\033[0K" echo -en "\r\033[0K"
echo -e "Fio binary download failed. Running dd test as fallback...." echo -e "Fio binary download failed. Running dd test as fallback...."
DD_FALLBACK=True DD_FALLBACK=True
@@ -864,14 +924,14 @@ if [ -z "$SKIP_IPERF" ]; then
IPERF_PATH=$YABS_PATH/iperf IPERF_PATH=$YABS_PATH/iperf
mkdir -p "$IPERF_PATH" mkdir -p "$IPERF_PATH"
# download iperf3 binary # download iperf3 binary from the binary release on the repo
if [[ -n $LOCAL_CURL ]]; then if [[ -n $LOCAL_CURL ]]; then
curl -s --connect-timeout 5 --retry 5 --retry-delay 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/iperf/iperf3_$ARCH -o "$IPERF_PATH/iperf3" curl -sfL --connect-timeout 5 --retry 5 --retry-delay 0 "https://github.com/masonr/yet-another-bench-script/releases/download/$IPERF_BIN_TAG/iperf3_$ARCH" -o "$IPERF_PATH/iperf3"
else else
wget -q -T 5 -t 5 -w 0 https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/bin/iperf/iperf3_$ARCH -O "$IPERF_PATH/iperf3" wget -q -T 5 -t 5 -w 0 "https://github.com/masonr/yet-another-bench-script/releases/download/$IPERF_BIN_TAG/iperf3_$ARCH" -O "$IPERF_PATH/iperf3"
fi fi
if [ ! -f "$IPERF_PATH/iperf3" ]; then # ensure iperf3 binary downloaded successfully if [ ! -s "$IPERF_PATH/iperf3" ]; then # ensure iperf3 binary downloaded successfully
IPERF_DL_FAIL=True IPERF_DL_FAIL=True
else else
chmod +x "$IPERF_PATH/iperf3" chmod +x "$IPERF_PATH/iperf3"
@@ -960,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"
@@ -974,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