b7e080ca
Make bench + profile workloads representative
a73x 2026-04-17 19:17
Replace the single-burst bench script with a bursty mixed workload (typing, ls, scrollback, long lines, clears) separated by small sleeps so the throttled render loop produces distinct frames per burst. Frame capture goes from 5 to ~65 (debug) / ~180 (ReleaseSafe). Drop the `sh -c` wrapper in `make profile` — it caused perf --no-inherit to sample only the shell parent (6 samples), not waystty. Running perf directly against the binary now captures ~1k samples. Move workload to tests/bench/workload.sh so it can be tuned without a zig recompile (embedded via addAnonymousImport). Baseline regenerated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
diff --git a/Makefile b/Makefile index 087369b..c3fb2cc 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ ZIG ?= zig FLAMEGRAPH ?= flamegraph.pl STACKCOLLAPSE ?= stackcollapse-perf.pl FLAMEGRAPH ?= inferno-flamegraph STACKCOLLAPSE ?= inferno-collapse-perf .PHONY: build run test bench profile clean test-render golden-update bench-baseline bench-check @@ -23,8 +23,8 @@ bench: zig-out/bin/waystty profile: $(ZIG) build -Doptimize=ReleaseSafe perf record -g -F 999 --no-inherit -o perf.data -- \ sh -c 'WAYSTTY_BENCH=1 ./zig-out/bin/waystty 2>bench.log' WAYSTTY_BENCH=1 perf record -g -F 999 --no-inherit -o perf.data -- \ ./zig-out/bin/waystty 2>bench.log perf script -i perf.data \ | $(STACKCOLLAPSE) \ | $(FLAMEGRAPH) > flamegraph.svg diff --git a/build.zig b/build.zig index 8afb3bf..de3b250 100644 --- a/build.zig +++ b/build.zig @@ -86,6 +86,9 @@ pub fn build(b: *std.Build) void { exe_mod.addImport("config", config_mod); exe_mod.addImport("frame_loop", frame_loop_mod); exe_mod.addImport("bench_stats", bench_stats_mod); exe_mod.addAnonymousImport("bench_workload", .{ .root_source_file = b.path("tests/bench/workload.sh"), }); const exe = b.addExecutable(.{ .name = "waystty", diff --git a/src/main.zig b/src/main.zig index 702cfdd..005e784 100644 --- a/src/main.zig +++ b/src/main.zig @@ -284,7 +284,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { defer alloc.free(shell); const bench_script: ?[:0]const u8 = if (is_bench) "echo warmup; sleep 0.2; seq 1 50000; find /usr/lib -name '*.so' 2>/dev/null | head -500; yes 'hello world' | head -2000; exit 0" @embedFile("bench_workload") else null; diff --git a/tests/bench/baseline.json b/tests/bench/baseline.json index e8b01a6..2f5c98c 100644 --- a/tests/bench/baseline.json +++ b/tests/bench/baseline.json @@ -1,38 +1,38 @@ { "workload_sha": "066a95eee2d2f6195c0eb997e7e18a63f75b48010b538dd287056f948cc65005", "workload_sha": "a79a3b3449f44938e56bc64555a95cc5234c73a1dc4b05c4e8cc17aa0209d1df", "zig_version": "0.15.2", "waystty_sha": "828c61f589b2bac3785e37531a094d6abb1f40ad", "frame_count": 5, "waystty_sha": "321b22803777191c86a97ad7ce7edba9b90b6c9e", "frame_count": 65, "sections": { "snapshot": { "min": 10, "avg": 201, "p99": 214, "max": 725 "min": 6, "avg": 42, "p99": 216, "max": 735 }, "row_rebuild": { "min": 115, "avg": 2075, "p99": 2166, "max": 5447 "min": 121, "avg": 1450, "p99": 3344, "max": 3383 }, "atlas_upload": { "min": 0, "avg": 10, "p99": 0, "max": 50 "avg": 4, "p99": 47, "max": 57 }, "instance_upload": { "min": 4, "avg": 37, "p99": 21, "max": 144 "min": 3, "avg": 17, "p99": 75, "max": 83 }, "gpu_submit": { "min": 37, "avg": 58, "p99": 66, "max": 79 "min": 22, "avg": 48, "p99": 99, "max": 106 } } } \ No newline at end of file diff --git a/tests/bench/workload.sh b/tests/bench/workload.sh new file mode 100644 index 0000000..d58d268 --- /dev/null +++ b/tests/bench/workload.sh @@ -0,0 +1,49 @@ #!/bin/sh # waystty bench workload — bursty mixed traffic so the throttled render # loop produces distinct frames per burst (instead of one coalesced dump). printf 'waystty bench workload\n' sleep 0.1 # Phase 1: typing-like — small lines, small gaps (~60 frames) i=1 while [ $i -le 60 ]; do printf '$ echo hello %d\nhello %d\n' $i $i sleep 0.02 i=$((i + 1)) done # Phase 2: ls-style bursts (~30 frames) i=1 while [ $i -le 30 ]; do ls /usr/lib 2>/dev/null | head -80 sleep 0.03 i=$((i + 1)) done # Phase 3: scrollback storms (~40 frames) i=1 while [ $i -le 40 ]; do seq 1 500 sleep 0.025 i=$((i + 1)) done # Phase 4: long-line wrapping (~30 frames) long=$(printf 'x%.0s' $(seq 1 160)) i=1 while [ $i -le 30 ]; do printf '%s\n%s\n%s\n' "$long" "$long" "$long" sleep 0.03 i=$((i + 1)) done # Phase 5: screen-clear + redraw (~20 frames) i=1 while [ $i -le 20 ]; do printf '\033[2J\033[H=== iter %d ===\n' $i sleep 0.04 i=$((i + 1)) done exit 0