diff --git a/AGENTS.md b/AGENTS.md index ffb0706b..92467bad 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -59,9 +59,9 @@ Inside pane-scaled render and layout loops: Prefer deterministic operation or architecture tests to wall-clock CI limits. Performance benchmarks are supporting evidence, not substitutes for behavioral coverage. Before a stable release, `just bench-release-smoke` must compare the -candidate with the current stable binary under hidden and visible output; use -the longer release matrix only when the smoke test moves materially or when -validating performance work. +candidate with the current stable binary under hidden and visible output. When +the result moves materially or when validating performance work, repeat it with +`HERDR_PERF_SAMPLE_SECONDS=60` and investigate the affected scenario. ### Runtime/client boundary guardrail diff --git a/justfile b/justfile index f4039a3d..396b85d3 100644 --- a/justfile +++ b/justfile @@ -73,7 +73,7 @@ build: bench-render-scale: cargo test --release --locked --bin herdr render_scale_profile -- --ignored --nocapture --test-threads=1 -# Fast end-to-end CPU comparison against the current stable release +# ~3-5 minute CPU comparison; downloads stable unless HERDR_PERF_BASELINE_BIN is set bench-release-smoke: cargo build --release --locked scripts/release_perf_smoke.sh "${CARGO_TARGET_DIR:-target}/release/herdr" @@ -135,7 +135,7 @@ release-docs-check: just website-build cd website && bun run build:draft -# Validate release docs and review full-render scaling before release preparation +# Validate release docs, render scaling, and end-to-end CPU before release preparation pre-release-check: just release-docs-check just bench-render-scale diff --git a/scripts/release_perf_case.sh b/scripts/release_perf_case.sh index 020b83fa..47d72259 100755 --- a/scripts/release_perf_case.sh +++ b/scripts/release_perf_case.sh @@ -50,7 +50,9 @@ cleanup() { tmux kill-session -t "$name" >/dev/null 2>&1 || true rm -rf "$state" } -trap cleanup EXIT INT TERM +trap cleanup EXIT +trap 'exit 130' INT +trap 'exit 143' TERM printf -v launch 'exec ' printf -v quoted '%q ' "${launch_env[@]}" "$bin" --session "$name" @@ -65,6 +67,8 @@ done [[ -n "$panes_json" ]] || { echo "session API did not become ready" >&2; exit 1; } root_pane=$(printf '%s\n' "$panes_json" | jq -r '.result.panes[0].pane_id') workspace_id=$("${control_env[@]}" "$bin" workspace list | jq -r '.result.workspaces[0].workspace_id') +[[ -n "$root_pane" && "$root_pane" != null ]] || { echo "session did not report a root pane" >&2; exit 1; } +[[ -n "$workspace_id" && "$workspace_id" != null ]] || { echo "session did not report a workspace" >&2; exit 1; } pane_file="$state/pane-ids.txt" printf '%s\n' "$root_pane" > "$pane_file" @@ -94,24 +98,23 @@ done [[ -n "$server_pid" ]] || { echo "could not find server pid" >&2; exit 1; } client_pid=$(tmux list-panes -s -t "$name" -F '#{pane_pid}') [[ -n "$client_pid" ]] || { echo "could not find client pid" >&2; exit 1; } -all_pids="$server_pid $client_pid" +all_pids=("$server_pid" "$client_pid") sleep "$warmup" raw="$out/cpu-raw.txt" if [[ $platform == linux ]]; then - pid_csv=$(printf '%s\n' $all_pids | paste -sd, -) + pid_csv=$(IFS=,; echo "${all_pids[*]}") LC_ALL=C pidstat -h -u -p "$pid_csv" 1 "$seconds" > "$raw" else top_args=(top -l $((seconds + 1)) -s 1 -stats pid,cpu,time -n 2) - for pid in $all_pids; do top_args+=(-pid "$pid"); done + for pid in "${all_pids[@]}"; do top_args+=(-pid "$pid"); done LC_ALL=C "${top_args[@]}" > "$raw" fi mean_linux() { awk -v target="$2" ' /^Linux/ || /^#/ || NF < 5 { next } - { found=0; for (i=1; i<=NF; i++) if ($i == target) { found=1; break } - if (found && $(NF-2) ~ /^[0-9]+([.][0-9]+)?$/) { sum += $(NF-2); count++ } } + $3 == target && $(NF-2) ~ /^[0-9]+([.][0-9]+)?$/ { sum += $(NF-2); count++ } END { if (!count) exit 1; printf "%.6f,%d", sum/count, count } ' "$1" } @@ -124,7 +127,7 @@ mean_macos() { } total=0 -for pid in $all_pids; do +for pid in "${all_pids[@]}"; do if [[ $platform == linux ]]; then parsed=$(mean_linux "$raw" "$pid"); else parsed=$(mean_macos "$raw" "$pid"); fi mean=${parsed%,*} samples=${parsed#*,} diff --git a/scripts/release_perf_producer.pl b/scripts/release_perf_producer.pl index b1bb1e4b..e99973cc 100755 --- a/scripts/release_perf_producer.pl +++ b/scripts/release_perf_producer.pl @@ -4,7 +4,11 @@ use warnings; use Time::HiRes qw(clock_gettime sleep CLOCK_MONOTONIC); my ($rate, $gate, $label) = @ARGV; -die "usage: $0