Disk IOPS test
Purpose: check that your validator’s disk is fast enough for X1 block production. This test safely benchmarks random read/write performance (IOPS) using the fio tool.
Run the test
Paste this entire block into your terminal:
# === X1 Validator Disk IOPS Quick Test (safe, file-based) ===
# Target: >= 20,000 IOPS for both 4K random reads and writes
set -euo pipefail
export LC_ALL=C
MNT="${MNT:-/var/tmp}"
SIZE_MB="${SIZE_MB:-2048}"
RUNTIME="${RUNTIME:-30}"
BS="${BS:-4k}"
JOBS="${JOBS:-4}"
IODEPTH="${IODEPTH:-32}"
ENGINE_CANDIDATES=("io_uring" "libaio")
PASS_THRESH="${PASS_THRESH:-20000}"
# Install fio automatically if missing
if ! command -v fio >/dev/null 2>&1; then
  echo "Installing fio..."
  sudo apt-get update -y >/dev/null 2>&1
  sudo apt-get install -y fio >/dev/null 2>&1
fi
ENGINE=""
for e in "${ENGINE_CANDIDATES[@]}"; do fio --enghelp 2>/dev/null | grep -q "$e" && ENGINE="$e" && break; done
[ -n "$ENGINE" ] || { echo "ERROR: Neither io_uring nor libaio available in fio."; exit 1; }
[ -d "$MNT" ] || { echo "ERROR: Mountpoint $MNT does not exist."; exit 1; }
[ -w "$MNT" ] || { echo "ERROR: $MNT is not writable."; exit 1; }
TESTDIR="$MNT/x1-fio-test.$$"
mkdir -p "$TESTDIR"
cd "$TESTDIR"
# --- Robust fio IOPS parser (handles commas, k/M suffixes, different formats) ---
run_fio_and_get_iops () {
  local NAME="$1" RW="$2"
  fio --name="$NAME" \
      --rw="$RW" \
      --bs="$BS" \
      --ioengine="$ENGINE" \
      --direct=1 \
      --group_reporting=1 \
      --time_based=1 \
      --runtime="$RUNTIME" \
      --numjobs="$JOBS" \
      --iodepth="$IODEPTH" \
      --size="${SIZE_MB}m" \
      --filename="$TESTDIR/fiofile.bin" \
      --random_generator=tausworthe64 \
      --fsync_on_close=1 \
      --output="$TESTDIR/${NAME}.out" >/dev/null
  # Try the headline "read/write: IOPS=..." line first, then fallback to the "iops : avg=..." line.
  awk '
    BEGIN{ OFMT="%.0f"; want=(tolower("'"$RW"'")=="randread" ? "read" : "write"); val=""; }
    {
      line=tolower($0)
      # Primary match: "read: IOPS=128k" or "write: IOPS=128,532"
      if (line ~ "^"want": " && line ~ /(iops|IOPS)=/) {
        if (match($0, /(IOPS|iops)=([0-9][0-9,\.]*)([kKmM]?)/, m)) {
          gsub(/,/, "", m[2]);  # remove thousands commas
          num=m[2]+0
          suf=tolower(m[3])
          if (suf=="k") num=num*1000
          else if (suf=="m") num=num*1000000
          printf("%.0f\n", num); exit
        }
      }
      # Fallback: summary line "iops        : avg=115058.64"
      if (line ~ /iops[[:space:]]*:[[:space:]]*.*avg=/) {
        if (match($0, /avg=([0-9][0-9,\.]*)/, m2)) {
          gsub(/,/, "", m2[1])
          num=m2[1]+0
          printf("%.0f\n", num); exit
        }
      }
    }
    END{
      if (NR>0) {}  # no-op
    }
  ' "$TESTDIR/${NAME}.out"
}
echo "Running 4K random READ test for ${RUNTIME}s..."
READ_IOPS="$(run_fio_and_get_iops "x1-randread" "randread" || true)"
READ_IOPS="${READ_IOPS:-0}"
echo "READ IOPS: $READ_IOPS"
echo "Running 4K random WRITE test for ${RUNTIME}s..."
WRITE_IOPS="$(run_fio_and_get_iops "x1-randwrite" "randwrite" || true)"
WRITE_IOPS="${WRITE_IOPS:-0}"
echo "WRITE IOPS: $WRITE_IOPS"
# Compare safely even if value is empty
passfail () {
  local val="${1:-0}" kind="$2"
  if [ "${val:-0}" -ge "${PASS_THRESH:-20000}" ]; then
    echo "PASS ($kind ≥ ${PASS_THRESH})"
  else
    echo "FAIL ($kind < ${PASS_THRESH})"
  fi
}
READ_VERDICT=$(passfail "$READ_IOPS" "read")
WRITE_VERDICT=$(passfail "$WRITE_IOPS" "write")
echo "==========================================="
echo "X1 Validator Disk IOPS Results (4K random)"
echo "  Read IOPS : $READ_IOPS    => $READ_VERDICT"
echo "  Write IOPS: $WRITE_IOPS   => $WRITE_VERDICT"
echo "  Threshold : ${PASS_THRESH} IOPS"
echo "  Params    : jobs=$JOBS iodepth=$IODEPTH bs=$BS engine=$ENGINE size=${SIZE_MB}MB runtime=${RUNTIME}s"
echo "Logs in     : $TESTDIR"
echo "==========================================="
echo ""
echo "=== fio raw output summary ==="
grep -i "iops" "$TESTDIR"/x1-randread.out || true
grep -i "iops" "$TESTDIR"/x1-randwrite.out || true
echo "=============================="
echo "Done."How to interpret results
You’ll see something like:
read: IOPS=128k, BW=499MiB/s
write: IOPS=113k, BW=442MiB/sDisk Type
Expected IOPS
Verdict
HDD
200–500
❌ Too slow
SATA SSD
5k–10k
⚠️ Weak
Consumer NVMe
50k–100k
✅ Good
Datacenter NVMe
100k–250k+
💎 Excellent
If both read and write ≥ 20,000 IOPS → ✅ your disk is ready for X1 mainnet validation.
Last updated

