fix(perf): bench jq direction bug + libaio + json note guard [#709]

- write tests read .write.* explicitly (jq // kept read=0 for writes)
- libaio1 installed everywhere (real aio engine, no sync cap)
- fio stdout notes stripped before jq parse

Ticket: https://projects.knownelement.com/issues/709
This commit is contained in:
2026-09-03 07:53:37 -05:00
parent 82fdb161cc
commit 7586605b70
4 changed files with 26 additions and 26 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
FROM debian:12-slim FROM debian:12-slim
RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \ RUN apt-get update -qq && apt-get install -y -qq --no-install-recommends \
fio iperf3 jq ca-certificates \ fio iperf3 jq libaio1 ca-certificates \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY bench-run.sh /usr/local/bin/bench-run.sh COPY bench-run.sh /usr/local/bin/bench-run.sh
+19 -21
View File
@@ -30,33 +30,31 @@ b meta path "$BENCH_DIR"
b meta runtime "$RUNTIME" b meta runtime "$RUNTIME"
b meta size "$SIZE" b meta size "$SIZE"
run_fio() { # $1=testname $2=fio-args... # fio may print human notes (e.g. sync-engine warnings) before the JSON on
local name="$1"; shift # stdout; strip everything before the opening brace so jq always gets JSON.
parse_fio() { # $1=json-file $2=testname $3=read|write
sed -n '/^{/,$p' "$1" | jq -r --arg n "$2" --arg d "$3" '
.jobs[0] as $j |
($n) + "|iops=" + ($j[$d].iops | tostring) + "|" +
"bw_kbps=" + ($j[$d].bw | tostring) + "|" +
"p99_ms=" + (($j[$d].clat_ns.percentile["99.000000"] // 0) / 1000000 | tostring)' | while IFS='|' read -r n rest; do
printf 'BENCH|%s|%s|%s\n' "$HOSTID" "$n" "$rest"
done
}
run_fio() { # $1=testname $2=read|write $3+=fio-args
local name="$1"; local dir="$2"; shift 2
fio --name="$name" --output-format=json --timeout=120 "$@" \ fio --name="$name" --output-format=json --timeout=120 "$@" \
> "$BENCH_DIR/.fio-out.json" 2>"$BENCH_DIR/.fio-err" || { > "$BENCH_DIR/.fio-out.json" 2>"$BENCH_DIR/.fio-err" || {
b "fio_${name}" ERROR; return; } b "fio_${name}" ERROR; return; }
if command -v jq >/dev/null 2>&1; then parse_fio "$BENCH_DIR/.fio-out.json" "$name" "$dir"
while IFS='|' read -r n rest; do
printf 'BENCH|%s|%s|%s\n' "$HOSTID" "$n" "$rest"
done < <(jq -r --arg n "$name" '
.jobs[0] as $j |
($n) + "|iops=" + ($j.read.iops // $j.write.iops | tostring) + "|" +
"bw_kbps=" + (($j.read.bw // $j.write.bw) | tostring) + "|" +
"p99_ms=" + (($j.read.clat_ns.percentile["99.000000"] // $j.write.clat_ns.percentile["99.000000"] // 0) / 1000000 | tostring)' \
"$BENCH_DIR/.fio-out.json")
else
# no jq: minimal grep fallback
grep -oE '"(iops|bw)":[0-9.]+' "$BENCH_DIR/.fio-out.json" | head -2 | while IFS=: read -r k v; do
b "fio_${name}_${k}" "$v"
done
fi
} }
# 4k random read/write (IOPS), 1M sequential read/write (MB/s); direct to skip cache # 4k random read/write (IOPS), 1M sequential read/write (MB/s); direct to skip cache
run_fio randread4k --filename="$BENCH_DIR/perf-test-file" --rw=randread --bs=4k --direct=1 --iodepth=16 --time_based --runtime="$RUNTIME" --size="$SIZE" run_fio randread4k read --filename="$BENCH_DIR/perf-test-file" --rw=randread --bs=4k --direct=1 --iodepth=16 --time_based --runtime="$RUNTIME" --size="$SIZE"
run_fio randwrite4k --filename="$BENCH_DIR/perf-test-file" --rw=randwrite --bs=4k --direct=1 --iodepth=16 --time_based --runtime="$RUNTIME" --size="$SIZE" run_fio randwrite4k write --filename="$BENCH_DIR/perf-test-file" --rw=randwrite --bs=4k --direct=1 --iodepth=16 --time_based --runtime="$RUNTIME" --size="$SIZE"
run_fio seqread1m --filename="$BENCH_DIR/perf-test-file" --rw=read --bs=1M --direct=1 --iodepth=8 --time_based --runtime="$RUNTIME" --size="$SIZE" run_fio seqread1m read --filename="$BENCH_DIR/perf-test-file" --rw=read --bs=1M --direct=1 --iodepth=8 --time_based --runtime="$RUNTIME" --size="$SIZE"
run_fio seqwrite1m --filename="$BENCH_DIR/perf-test-file" --rw=write --bs=1M --direct=1 --iodepth=8 --time_based --runtime="$RUNTIME" --size="$SIZE" run_fio seqwrite1m write --filename="$BENCH_DIR/perf-test-file" --rw=write --bs=1M --direct=1 --iodepth=8 --time_based --runtime="$RUNTIME" --size="$SIZE"
rm -f "$BENCH_DIR/.fio-out.json" "$BENCH_DIR/.fio-err" rm -f "$BENCH_DIR/.fio-out.json" "$BENCH_DIR/.fio-err"
+1 -1
View File
@@ -5,5 +5,5 @@
set -eu set -eu
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
apt-get update -qq apt-get update -qq
apt-get install -y -qq fio iperf3 jq >/dev/null apt-get install -y -qq fio iperf3 jq libaio1 >/dev/null
echo "bench toolset installed: fio=$(fio --version 2>/dev/null | awk '{print $3}') iperf3=$(iperf3 --version 2>/dev/null | awk 'NR==1{print $2}')" echo "bench toolset installed: fio=$(fio --version 2>/dev/null | awk '{print $3}') iperf3=$(iperf3 --version 2>/dev/null | awk 'NR==1{print $2}')"
+5 -3
View File
@@ -33,8 +33,10 @@ trap cleanup EXIT
TPL=$(pveam list local 2>/dev/null | grep -oE 'local:vztmpl/[a-z0-9-]*debian-12-standard[^ ]*\.tar\.zst' | head -1 || true) TPL=$(pveam list local 2>/dev/null | grep -oE 'local:vztmpl/[a-z0-9-]*debian-12-standard[^ ]*\.tar\.zst' | head -1 || true)
if [ -z "$TPL" ]; then if [ -z "$TPL" ]; then
pveam update >/dev/null pveam update >/dev/null
pveam download local debian-12-standard_12.7-1_amd64.tar.zst >/dev/null DL=$(pveam available --section system 2>/dev/null | grep -oE 'debian-12-standard[^ ]*\.tar\.zst' | sort -V | tail -1)
TPL=$(pveam list local | grep -oE 'local:vztmpl/[a-z0-9-]*debian-12-standard[^ ]*\.tar\.zst' | head -1) [ -n "$DL" ] || { echo "[bench-lxc] ERROR: no debian-12 LXC template in pveam" >&2; exit 1; }
pveam download local "$DL" >/dev/null
TPL=$(pveam list local | grep -oE "local:vztmpl/$DL" | head -1)
fi fi
echo "[bench-lxc] template: $TPL" echo "[bench-lxc] template: $TPL"
@@ -50,7 +52,7 @@ pct start "$CTID"
sleep 5 sleep 5
# toolset in (same installer the guests use; piped in, nothing fetched from outside) # toolset in (same installer the guests use; piped in, nothing fetched from outside)
pct exec "$CTID" -- bash -c "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq >/dev/null; apt-get install -y -qq fio iperf3 jq >/dev/null" pct exec "$CTID" -- bash -c "export DEBIAN_FRONTEND=noninteractive; apt-get update -qq >/dev/null; apt-get install -y -qq fio iperf3 jq libaio1 >/dev/null"
BDIR="/mnt/bench" BDIR="/mnt/bench"
[ -z "$STORE" ] && BDIR="/var/tmp" [ -z "$STORE" ] && BDIR="/var/tmp"