# DiskOps (CLI prototype)
This working prototype is a sequential disk I/O throughput benchmark: it
writes a temp file into a target directory in fixed-size chunks, fsyncs it
to force the data to stable storage, times the write, then closes and
reopens the file and reads it back sequentially, reporting write and read
throughput in MB/s. Be clear-eyed about what this is: it measures file-API
throughput through the OS and filesystem against the target directory, NOT
raw block-device performance. The full DiskOps product concept also covers
partitioning, cloning, migration, and SMART awareness - those all need
raw-device access and OS-privileged operations that cannot be implemented
portably with only the Go standard library (no external deps, no OS-specific
syscalls/build tags), so they are on the roadmap rather than in this
prototype. See ../plan.md for the full product plan.
## Build from source
Requires Go 1.24+, no external dependencies.
go build -o diskops .
Cross-compile for another platform:
GOOS=windows GOARCH=amd64 go build -o diskops.exe .
GOOS=darwin GOARCH=arm64 go build -o diskops .
## Usage
diskops bench
[--size 256MB] [--block 1MB] [--json]
Runs a sequential write-then-read benchmark against a temp file created at
/.diskops-benchmark-tmp, and reports throughput in MB/s. The temp file
is always deleted afterward, including on error paths.
Flags:
--size Total bytes to write/read, e.g. 256MB, 1GiB, 512KB (default 256MB).
Accepts SI suffixes (KB/MB/GB, powers of 1000) and binary
suffixes (KiB/MiB/GiB, powers of 1024), case-insensitive. A bare
number is treated as a byte count.
--block Chunk size for each write/read call, e.g. 1MB, 256KB (default 1MB).
Same suffix rules as --size. Does not need to divide --size
evenly - the last chunk is simply shorter.
--json Emit a machine-readable JSON report instead of human-readable text.
How the benchmark works:
- One random block of size --block is pre-generated with crypto/rand and
reused for every chunk written. Genuinely random (not repeating
zero/pattern) data is used so filesystem-level compression or dedup
can't skew the numbers, but generating fresh random data for every chunk
with crypto/rand is slow enough to dominate the timed write loop and
artificially cap the reported throughput - so the random-generation cost
is paid once, up front, outside the timer, and the same block is reused.
- The write phase is timed from the first byte written through a final
f.Sync() call. Without the fsync, the benchmark would only measure how
fast data lands in the OS page cache, not how fast it reaches stable
storage, so the fsync is deliberately included in the timed write.
- The read phase closes and reopens the file, then reads it back
sequentially in --block-sized chunks into a reused buffer (the data
itself is discarded, not compared).
Caveats:
- This is sequential, single-threaded, file-API throughput only - it does
not reflect random I/O, queue depth, or raw block-device performance.
- OS and filesystem caching mean small --size values can report
unrealistically high numbers (especially on the read side, where a
small file may be served entirely from cache). Use --size of at least a
few hundred MB for a meaningful result. Smaller sizes still work and are
useful for a quick sanity check in constrained test environments - the
tool does not enforce a minimum.
Example:
$ diskops bench /mnt/data --size 512MB --block 1MB
DiskOps sequential benchmark
target dir: /mnt/data
total size: 488.28 MiB (512000000 bytes)
block size: 976.56 KiB (1000000 bytes)
write: 412.30 MB/s (1.242s, includes fsync)
read: 891.15 MB/s (0.575s)
Note: sequential, single-threaded, file-API throughput against the target
filesystem - not a raw block-device benchmark. Small --size values can be
inflated by OS/filesystem caching; use a few hundred MB or more for a
meaningful number.
## Prebuilt binaries
See ../downloads/ for prebuilt binaries (Windows/macOS/Linux) and
CHECKSUMS.txt for their SHA-256 hashes. These are unsigned indie builds -
Windows SmartScreen and macOS Gatekeeper will warn on first run, which is
expected until a code-signing certificate is in place.