a73x

delta: dumpVtRow allocates and frees per row, 50x per pty read

open   by a73x

`DeltaTracker.update` allocates and frees one buffer per row per pty read —
50 alloc/free pairs per read at 50 rows, through Zig's GPA
(`heap.debug_allocator.DebugAllocator`), which showed up at ~5% of daemon
cycles in the 2026-08-21 profile plus an unmeasured share of `memset`.

`dumpVtRow` returns an owned slice by contract, which is what forces the
churn. Formatting into a caller-provided writer (one buffer reused across
all rows, cleared per row) removes it. Unlike the detached-session fix,
this one helps the attached case too, since the loop runs either way.

Comments

a73x   2026-08-21 14:40

Re-ranked upward: this is the biggest of the three, not the cheap
cleanup the ~5% in the opening note suggested. That figure came from a
user-space perf profile, which structurally cannot see where the cost
actually lands.

Measured 2026-08-21 on 374MB of full-width repaint, 200x50, no client,
ReleaseSafe, while landing the detached-session fix:

    utime 24.1s   stime 106.5s      <- 81% of CPU in the KERNEL

Fifty GPA allocations per pty read churn mmap/munmap and page faults.
In perf those frames come back as unresolved [unknown] addresses (~11%
of samples), so the profile attributed 57% to the formatter and ~5% to
the allocator — the formatter was only the visible half. Removing the
whole loop for detached sessions cut instructions 5.9x but wall time
27x; the missing 4.7x was system time.

The detached fix does nothing for a session with a client attached,
where this loop still runs on every read. This issue is what covers
that case, and it is a smaller change than the cell-hashing one.