bench_async_uring.py
text/x-python
Filename: bench_async_uring.py
Type: text/x-python
Part: 0
#!/usr/bin/env python3
import argparse
import json
import subprocess
import sys
def run_fio(directory, nblocks, iodepth, force_async,
size,
runtime):
bs = nblocks * 8 * 1024
cmd = [
"fio",
f"--directory={directory}",
f"--size={size}",
"--name=read",
"--invalidate=0",
"--rw=read",
"--direct=0",
"--buffered=1",
"--time_based=1",
f"--runtime={runtime}",
"--ioengine=io_uring",
f"--iodepth={iodepth}",
f"--force_async={force_async}",
f"--bs={bs}",
"--output-format=json",
]
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
return json.loads(result.stdout)
def extract_metrics(data):
"""
Extract bandwidth (GiB/s) and average latency (µs) from fio JSON.
fio JSON reports.:
"""
read_stats = data["jobs"][0]["read"]
bw_kibs = read_stats["bw"] # KiB/s
bw_gibs = bw_kibs / 1024**2 # KiB/s → GiB/s
lat_ns = read_stats["lat_ns"]["mean"] # nanoseconds
lat_usec = lat_ns / 1000.0 # → µs
return bw_gibs, lat_usec
def main():
parser = argparse.ArgumentParser(
description="Run fio sequential read benchmarks across parameter combos."
)
parser.add_argument(
"--directory", default="/srv/fio",
help="fio test directory (default: /srv/fio)",
)
parser.add_argument(
"--size", default="4GiB",
help="fio file size (default: 4GiB)",
)
parser.add_argument(
"--runtime", type=int, default=1,
help="Seconds per test (default: 1)",
)
parser.add_argument(
"--nblocks", type=int, nargs="+",
default=[1, 2, 4, 8, 16, 32, 64, 128],
help="Block-count values to test (bs = nblocks * 8 KiB)",
)
parser.add_argument(
"--iodepths", type=int, nargs="+",
default=[1, 2, 4, 8, 16, 32],
help="iodepth values to test",
)
args = parser.parse_args()
print("nblocks\tiod\tasync\tbw_gib_s\tlat_usec")
for nblocks in args.nblocks:
for iodepth in args.iodepths:
for force_async in [0, 1]:
try:
data = run_fio(
directory=args.directory,
nblocks=nblocks,
iodepth=iodepth,
force_async=force_async,
size=args.size,
runtime=args.runtime,
)
bw_gibs, lat_usec = extract_metrics(data)
print(f"{nblocks}\t{iodepth}\t{force_async}\t{bw_gibs:.4f}\t{lat_usec:.4f}")
sys.stdout.flush()
except subprocess.CalledProcessError as exc:
print(f"# ERROR nblocks={nblocks} iod={iodepth} async={force_async}: {exc}",
file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()