# Disk IOPS test

### Run the test

Paste this entire block into your terminal:

```bash
# === 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/s
```

| Disk 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.x1.xyz/validating/performance/disk-iops-test.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
