SSD RAID Benchmark, Part 2 — Linux (WSL Ubuntu) with fio

Created: | Updated:

Intro.

This is Part 2 of the SSD test series. In Part 1 I benchmarked two SATA SSDs on Windows 11 across Non-RAID, RAID 0 and RAID 1 using Microsoft DiskSpd. Here I run the same disks, same machine, same test matrix — but on Linux, inside Windows' WSL Ubuntu, using fio (the Linux counterpart of DiskSpd). The goal is a clean, apples-to-apples look at how the same storage behaves under a different OS, and what the numbers say when you put Windows and Linux side by side on identical hardware.

To keep this focused, I'm not repeating the hardware, BIOS/Intel-RST setup, RAID 0 vs RAID 1 theory, or the detailed test-case definitions — those are all in Part 1. This post covers only what's new for Linux: the disk preparation, the fio-based test tool, the Ubuntu results, and the cross-platform comparison.

Keeping the series consistent

The whole point of a series is that the runs are comparable, so the Linux side was built to match Part 1 exactly:

The only intentional variable is the OS/engine: Windows + DiskSpd vs. Linux + fio.

1. Preparing the Disks for WSL Ubuntu

What WSL actually is (and isn't). WSL 2 — the current default — is not a native OS and not a syscall-translation shim. It runs a real Linux kernel inside a lightweight Hyper-V–based virtual machine that boots in the background alongside Windows. So this is genuine Linux (real kernel, real ext4, real fio), but every disk I/O and system call still passes through a thin virtualization layer — which is why the results later carry some WSL overhead versus bare-metal Linux. (The older WSL 1 was different: no Linux kernel and no VM, just a compatibility layer translating Linux system calls to the Windows NT kernel. The runs here all use WSL 2.)

Because it's a VM with a real kernel, WSL 2 can attach a physical disk directly with wsl --mount, so Ubuntu sees the real block devices rather than a Windows drive-letter share. The catch: Windows holds an exclusive lock on a disk it has online, so each disk must be taken offline in Windows first, then bare-mounted into WSL and formatted as a native Linux filesystem (ext4).

Step 1 — In Windows (elevated PowerShell), take the disk(s) offline:

Get-Disk                              # find the target DiskNumber
Set-Disk -Number 1 -IsOffline $true   # release Windows' exclusive lock

Step 2 — Attach the raw disk(s) into WSL:

wsl --mount \\.\PHYSICALDRIVE1 --bare
wsl --mount \\.\PHYSICALDRIVE2 --bare
# --bare = expose as a raw block device; WSL does not auto-mount/format it

Step 3 — In Ubuntu, format as ext4 and mount:

lsblk                          # identify the new devices (e.g. /dev/sde, /dev/sdf)
sudo wipefs -a /dev/sde        # * DESTRUCTIVE: erases the existing partition table
sudo mkfs.ext4 /dev/sde        # whole-disk ext4
sudo mkdir -p /mnt/raid0test
sudo mount /dev/sde /mnt/raid0test
sudo chown $(whoami):$(whoami) /mnt/raid0test
Why ext4, not just the NTFS drive? You can point the benchmark at the Windows drive through WSL's /mnt/e, but that path goes over the DrvFs (9P) translation layer and measures that overhead, not the disk. To measure Linux filesystem performance honestly, the disk must be a real ext4 volume. Note that reformatting to ext4 destroys the NTFS data on that disk — do this only on disks you can wipe.

Step 4 — When finished, hand the disk back to Windows:

# in Ubuntu
sudo umount /mnt/raid0test
# in Windows
wsl --unmount \\.\PHYSICALDRIVE1
Set-Disk -Number 1 -IsOffline $false   # back online (reformat to NTFS to reuse)

The full step-by-step, including the Non-RAID two-disk case, is in Windows_WSL_Ubuntu_Disk_Preparation.txt in the repo.

2. The Test Program — run-disk-benchmark.sh (fio)

The Linux tool is run-disk-benchmark.sh, the direct counterpart of Part 1's Run-DiskBenchmark.ps1. It swaps the engine from DiskSpd to fio but runs the same 6-test matrix, samples CPU/memory/disk utilization once per second during each run (from /proc), and writes a timestamped CSV with the identical column layout. Both scripts live in one repo: github.com/devdama/disk-benchmark.

Setup and run:

sudo apt install fio jq          # fio = engine, jq = parse fio's JSON output

# Non-RAID: measure the two mount points individually
./run-disk-benchmark.sh --targets /mnt/nonraid1,/mnt/nonraid2 --config NonRAID

# RAID 0 / RAID 1 arrays (single mount point)
./run-disk-benchmark.sh --targets /mnt/raid0test --config RAID0
./run-disk-benchmark.sh --targets /mnt/raid1test --config RAID1

The six fio jobs map one-to-one onto the DiskSpd tests from Part 1:

SEQ1M-Q8T1-Read     --rw=read      --bs=1M --iodepth=8  --numjobs=1
SEQ1M-Q8T1-Write    --rw=write     --bs=1M --iodepth=8  --numjobs=1
RND4K-Q32T16-Read   --rw=randread  --bs=4k --iodepth=32 --numjobs=16
RND4K-Q32T16-Write  --rw=randwrite --bs=4k --iodepth=32 --numjobs=16
RND4K-Q1T1-Read     --rw=randread  --bs=4k --iodepth=1  --numjobs=1
RND4K-Q1T1-Write    --rw=randwrite --bs=4k --iodepth=1  --numjobs=1
# common: --direct=1 --ioengine=libaio --size=8G --runtime=30 --ramp_time=5 --time_based=1

--direct=1 bypasses the Linux page cache (the equivalent of DiskSpd's -Sh), and --ioengine=libaio issues asynchronous I/O so --iodepth is actually meaningful. Root isn't required for cache bypass, but running with sudo avoids permission issues on the mount points.

3. Ubuntu Results

Numbers are fio's reported MB/s, IOPS and average latency. Non-RAID is the average of the two mount points; RAID 0 and RAID 1 are the single array. As in Part 1, each chart uses the metric that matters for that workload (throughput for all six tests; IOPS for the random tests; latency for the responsiveness-sensitive cases), and the full tables below carry every number.

Linux throughput chart
Throughput (MB/s). On Linux, RAID 0 again roughly doubles sequential read and write; RAID 1's sequential read gains little here and its write stays around single-disk.
Linux random 4K IOPS chart
Random 4K IOPS. RAID 0 leads on both read and write; RAID 1's random write again dips near/below Non-RAID (the mirror write penalty).
Linux latency chart
Average latency (ms, lower is better). RAID 0 has the lowest sequential latency; QD1 random latency is similar across configs.

Sequential throughput (SEQ1M Q8T1)

TestNon-RAIDRAID 0RAID 1
Read (MB/s)6081140647
Write (MB/s)4961022450

Random 4K, high queue (RND4K Q32T16) — IOPS

TestNon-RAIDRAID 0RAID 1
Read (IOPS)54,300108,04892,234
Write (IOPS)63,860121,63257,881

Random 4K, QD1 responsiveness (RND4K Q1T1) — latency

TestNon-RAIDRAID 0RAID 1
Read (ms)0.1710.1800.192
Write (ms)0.0850.0970.100

4. Windows vs Linux — Same Machine

Here's the interesting part: identical disks and arrays, measured on each OS. The picture is mixed — neither platform wins everywhere.

Sequential throughput Windows vs Linux
Sequential throughput. Linux edges Windows on most sequential cases — most notably RAID 0 write (1022 vs 969 MB/s) and Non-RAID read (608 vs 559 MB/s).
Random 4K QD32 IOPS Windows vs Linux
Random 4K QD32 IOPS. Windows posts much higher parallel random reads (e.g. RAID 1 157k vs 92k), while Linux leads on some random writes (RAID 0 122k vs 107k).

Two patterns stand out:

Read this as WSL, not "Linux vs Windows" in the abstract. The Linux run happens inside WSL 2, which is a lightweight virtual machine. Even with a disk bare-mounted as native ext4, every I/O still crosses the WSL 2 virtualization layer, and the utilization counters come from inside that VM. That overhead is the most likely explanation for the higher QD1 latency and lower high-queue random-read IOPS on the Linux side. A bare-metal Linux install would very likely narrow — or change — these gaps. The comparison is fair and useful for a WSL workflow; it is not a verdict on native Linux storage performance.

Final Takeaway

The RAID story is the same on both platforms, which is reassuring: RAID 0 roughly doubles sequential throughput and leads random I/O, while RAID 1 matches single-disk writes and pays a small random-write penalty for its redundancy. On top of that, the OS layer clearly matters: on this machine Linux/fio was a touch faster for sequential streaming, while Windows/DiskSpd reported markedly higher high-queue random reads — with the caveat that the Linux numbers carry WSL 2 virtualization overhead. The practical lesson is that a benchmark measures hardware + OS + engine together, so cross-platform numbers are only meaningful when, as here, every other variable is pinned down.

Next in the series: a native (bare-metal) Linux run to isolate how much of the gap above is really WSL, plus a planned macOS script.