a73x

13a38303

Add WAYSTTY_BENCH_UNTHROTTLED escape hatch

a73x   2026-04-16 11:28

Bypasses FrameLoop gating and callback requests in bench mode for raw
throughput measurement. Explicitly not freeze-safe — documented in the
spec. Emits a banner on startup so bench logs are unambiguous.

diff --git a/src/main.zig b/src/main.zig
index 04cb502..fa306c8 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -212,6 +212,17 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
    else
        null;

    const bench_unthrottled = std.posix.getenv("WAYSTTY_BENCH") != null
        and std.posix.getenv("WAYSTTY_BENCH_UNTHROTTLED") != null;

    if (std.posix.getenv("WAYSTTY_BENCH") != null) {
        if (bench_unthrottled) {
            std.debug.print("[bench] mode: UNTHROTTLED (not freeze-safe)\n", .{});
        } else {
            std.debug.print("[bench] mode: THROTTLED (vsync-paced)\n", .{});
        }
    }

    var p = try pty.Pty.spawn(.{
        .cols = cols,
        .rows = rows,
@@ -328,7 +339,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
        }

        if (!shouldRenderFrame(render_pending, false, false)) continue;
        if (!frame_loop.canRender()) continue; // hidden — no Vulkan at all
        if (!bench_unthrottled and !frame_loop.canRender()) continue; // hidden — no Vulkan at all

        // applyPendingScale — Vulkan work, gated on canRender().
        if (scale_pending) {
@@ -608,7 +619,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
        }

        clearConsumedDirtyFlags(&term.render_state.dirty, dirty_rows, refresh_plan);
        try frame_loop.commitRender();
        if (!bench_unthrottled) try frame_loop.commitRender();
        render_pending = false;
    }