#!/usr/bin/env bash # # WHB Server Benchmark v1.0 # by Web Hosting Benchmark — https://www.webhostingbenchmark.com/tools/benchmark/ # # Measures CPU speed, memory bandwidth, disk throughput, disk IOPS and network # speed on the server it runs on, then rates the host on a 0-100% scale. # # Usage: curl -sL https://www.webhostingbenchmark.com/tools/benchmark.sh | bash # # Safe by design: writes only inside a temp directory it removes afterwards, # needs no root, installs nothing, sends nothing anywhere. set -u LC_ALL=C TESTDIR="${TMPDIR:-/tmp}/whb-bench.$$" mkdir -p "$TESTDIR" || { echo "Cannot create temp dir"; exit 1; } trap 'rm -rf "$TESTDIR"' EXIT INT TERM # ---------------------------------------------------------------- helpers --- now_ms() { local t t=$(date +%s%3N 2>/dev/null) case "$t" in *N*|'') echo $(( $(date +%s) * 1000 ));; *) echo "$t";; esac } # log-scale score: 0 at $2 (floor), 100 at $3 (ceiling) score() { awk -v v="$1" -v lo="$2" -v hi="$3" 'BEGIN { if (v <= lo) { print 0; exit } s = 100 * log(v/lo) / log(hi/lo) if (s > 100) s = 100 printf "%.0f", s }' } fmt() { awk -v v="$1" 'BEGIN { printf (v>=100 ? "%.0f" : "%.1f"), v }'; } hr() { printf '%s\n' "--------------------------------------------------------------"; } echo echo " WHB Server Benchmark v1.0 | webhostingbenchmark.com" hr echo " Host : $(hostname 2>/dev/null || echo unknown)" echo " Kernel : $(uname -sr 2>/dev/null || echo unknown)" CORES=$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1) CPUMODEL=$(grep -m1 'model name' /proc/cpuinfo 2>/dev/null | cut -d: -f2- | sed 's/^ //') echo " CPU : ${CPUMODEL:-unknown} (${CORES} core(s))" MEMTOTAL=$(awk '/MemTotal/ {printf "%.1f GB", $2/1048576}' /proc/meminfo 2>/dev/null) echo " Memory : ${MEMTOTAL:-unknown}" hr # ------------------------------------------------------ 1. CPU single-core -- printf " [1/7] CPU single-core (SHA-256 hashing) ... " T0=$(now_ms) dd if=/dev/zero bs=1M count=256 2>/dev/null | sha256sum > /dev/null 2>&1 \ || dd if=/dev/zero bs=1M count=256 2>/dev/null | shasum -a 256 > /dev/null T1=$(now_ms) CPU1=$(awk -v ms=$((T1-T0)) 'BEGIN { printf "%.1f", 256000/ms }') # MB/s echo "${CPU1} MB/s" S_CPU1=$(score "$CPU1" 40 1500) # ------------------------------------------------------- 2. CPU multi-core -- printf " [2/7] CPU multi-core (%s threads) ... " "$CORES" T0=$(now_ms) i=0 while [ "$i" -lt "$CORES" ] && [ "$i" -lt 16 ]; do dd if=/dev/zero bs=1M count=128 2>/dev/null | sha256sum > /dev/null 2>&1 & i=$((i+1)) done wait T1=$(now_ms) CPUN=$(awk -v ms=$((T1-T0)) -v n="$i" 'BEGIN { printf "%.1f", n*128000/ms }') echo "${CPUN} MB/s" S_CPUN=$(score "$CPUN" 80 8000) # --------------------------------------------------- 3. memory bandwidth ---- printf " [3/7] Memory bandwidth ... " T0=$(now_ms) dd if=/dev/zero of=/dev/null bs=1M count=8192 2>/dev/null T1=$(now_ms) MEMBW=$(awk -v ms=$((T1-T0)) 'BEGIN { printf "%.1f", 8192/ms }') # GB/s echo "${MEMBW} GB/s" S_MEM=$(score "$MEMBW" 0.8 25) # --------------------------------------------- 4. disk sequential write ----- printf " [4/7] Disk sequential write (256 MB, fsync) ... " T0=$(now_ms) dd if=/dev/zero of="$TESTDIR/seq" bs=1M count=256 conv=fdatasync 2>/dev/null T1=$(now_ms) SEQW=$(awk -v ms=$((T1-T0)) 'BEGIN { printf "%.1f", 256000/ms }') echo "${SEQW} MB/s" S_SEQW=$(score "$SEQW" 40 2500) # ---------------------------------------------- 5. disk sequential read ----- printf " [5/7] Disk sequential read ... " T0=$(now_ms) if dd if="$TESTDIR/seq" of=/dev/null bs=1M iflag=direct 2>/dev/null; then DIRECT=" (direct)"; else dd if="$TESTDIR/seq" of=/dev/null bs=1M 2>/dev/null; DIRECT=" (cached)" fi T1=$(now_ms) [ $((T1-T0)) -lt 1 ] && T1=$((T0+1)) SEQR=$(awk -v ms=$((T1-T0)) 'BEGIN { printf "%.1f", 256000/ms }') echo "${SEQR} MB/s${DIRECT}" S_SEQR=$(score "$SEQR" 80 4000) # --------------------------------------------------------- 6. disk IOPS ----- printf " [6/7] Disk IOPS (4K random write) ... " if command -v fio > /dev/null 2>&1; then IOPS=$(fio --name=whb --directory="$TESTDIR" --rw=randwrite --bs=4k --size=64M \ --direct=1 --runtime=8 --time_based --ioengine=psync --fdatasync=1 \ --minimal 2>/dev/null | awk -F';' '{print $49}' | cut -d. -f1) METHOD="fio" fi if [ -z "${IOPS:-}" ] || [ "${IOPS:-0}" = "0" ]; then # fallback: 1000 synced 4K writes in a single dd run (measures durable # write latency; scored on its own scale since synced IOPS cap far below # async fio numbers even on NVMe) N=1000 T0=$(now_ms) dd if=/dev/zero of="$TESTDIR/iops" bs=4k count=$N oflag=dsync 2>/dev/null T1=$(now_ms) [ $((T1-T0)) -lt 1 ] && T1=$((T0+1)) IOPS=$(awk -v ms=$((T1-T0)) -v n="$N" 'BEGIN { printf "%.0f", n*1000/ms }') METHOD="dd-sync" fi if [ "$METHOD" = "fio" ]; then S_IOPS=$(score "$IOPS" 60 40000) else S_IOPS=$(score "$IOPS" 50 8000) fi echo "${IOPS} IOPS (${METHOD})" [ "$METHOD" = "dd-sync" ] && echo " (tip: install fio for a more accurate random-IO figure)" # ---------------------------------------------------------- 7. network ------ printf " [7/7] Network download (25 MB via Cloudflare) ... " NETBPS=$(curl -sL -o /dev/null --max-time 30 \ -w '%{speed_download}' 'https://speed.cloudflare.com/__down?bytes=26214400' 2>/dev/null | cut -d. -f1) if [ -n "${NETBPS:-}" ] && [ "${NETBPS:-0}" -gt 0 ] 2>/dev/null; then NET=$(awk -v b="$NETBPS" 'BEGIN { printf "%.1f", b/1048576 }') # MB/s echo "${NET} MB/s" S_NET=$(score "$NET" 1 120) else NET="" S_NET="" echo "skipped (no internet access or curl missing)" fi # ------------------------------------------------------------- results ------ # weights (%): cpu1 15, cpuN 15, mem 10, seqw 15, seqr 10, iops 25, net 10 TOTAL=$(awk -v a="$S_CPU1" -v b="$S_CPUN" -v c="$S_MEM" -v d="$S_SEQW" \ -v e="$S_SEQR" -v f="$S_IOPS" -v g="${S_NET:--1}" 'BEGIN { w = 15+15+10+15+10+25; s = a*15+b*15+c*10+d*15+e*10+f*25 if (g >= 0) { w += 10; s += g*10 } printf "%.0f", s/w }') if [ "$TOTAL" -ge 90 ]; then GRADE="A+ Exceptional" elif [ "$TOTAL" -ge 80 ]; then GRADE="A Excellent" elif [ "$TOTAL" -ge 70 ]; then GRADE="B+ Very good" elif [ "$TOTAL" -ge 60 ]; then GRADE="B Good" elif [ "$TOTAL" -ge 50 ]; then GRADE="C Average" elif [ "$TOTAL" -ge 35 ]; then GRADE="D Below average" else GRADE="F Poor" fi echo hr echo " RESULTS value score /100" hr printf " CPU single-core %15s MB/s %10s\n" "$CPU1" "$S_CPU1" printf " CPU multi-core %15s MB/s %10s\n" "$CPUN" "$S_CPUN" printf " Memory bandwidth %15s GB/s %10s\n" "$MEMBW" "$S_MEM" printf " Disk seq. write %15s MB/s %10s\n" "$SEQW" "$S_SEQW" printf " Disk seq. read %15s MB/s %10s\n" "$SEQR" "$S_SEQR" printf " Disk IOPS (4K) %15s %10s\n" "$IOPS" "$S_IOPS" [ -n "$NET" ] && printf " Network download %15s MB/s %10s\n" "$NET" "$S_NET" hr printf " OVERALL HOST RATING: %s%% — %s\n" "$TOTAL" "$GRADE" hr echo " Compare hosts and read reviews: https://www.webhostingbenchmark.com/" echo