diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-30 14:25:52 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:17 -0300 |
| commit | 1d0f8cd158bb47941c0187d32422787c92e8feeb (patch) | |
| tree | b7f6806cc431c5e2339cdd4887405275a6f2c635 /src/detached/server.zig | |
| parent | 69c5e62fe45a3768edff14993789f2aadfafadec (diff) | |
| download | pardes-1d0f8cd158bb47941c0187d32422787c92e8feeb.tar.gz pardes-1d0f8cd158bb47941c0187d32422787c92e8feeb.zip | |
A detached session no client watches draws no frames: yes | head -c 50M through pty/run goes from over 30 s to 11 s
Profiling the 50 MB run showed 70% of its time in draw.render,
recolorAnsi alone 43%, walking cells through PageList.pin. The detached
session drew a frame after every pty read, with no client attached to
see it. A host now says whether anyone watches (Host.VTable.watched). The
detached server answers whether a client is attached, and while none is
the core keeps the frame owed instead of drawing it. A /screen read draws
its own, and a client attaching gets one (hello sets needs_frame).
Debug, 80x24: 10 MB went from 7.36 s to 2.10 s, and 50 MB from over the
30 s client timeout (about 37 s by rate) to 11.08 s. What is left is the
terminal's own parsing and scrollback growth. A session a frontend shows
still draws after every read. Pacing those frames is the next step if
that case matters.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/detached/server.zig')
| -rw-r--r-- | src/detached/server.zig | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig index d8379793..001acc47 100644 --- a/src/detached/server.zig +++ b/src/detached/server.zig @@ -376,6 +376,7 @@ pub const Session = struct { .now = clockNow, .present = present, .poll_frame = pollFrame, + .watched = watched, .spawn = spawn, .pty_write = ptyWrite, .pty_resize = ptyResize, @@ -641,6 +642,12 @@ pub const Session = struct { s.mailbox.signal(); } + fn watched(ctx: ?*anyopaque) bool { + const s = of(ctx); + for (&s.clients) |*c| if (c.attached) return true; + return false; + } + fn pollFrame(ctx: ?*anyopaque) void { const s = of(ctx); if (s.ninep) |l| s.ninep_pending = l.tick().pending; @@ -1052,6 +1059,9 @@ pub const Session = struct { c.attached = true; c.need_full = true; c.greet = true; + // Unwatched until now, it may have drawn nothing: a frame + // for the one attaching (watched). + s.core.needs_frame = true; }, .bye => s.close(c, .bye), .event => |ev| { |
