> For the complete documentation index, see [llms.txt](https://docs.x1.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.x1.xyz/validating/performance/disk-iops-test.md).

# 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
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
