From be5f559939fc11cbfba95b4a7d518816bec8677a Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 13:26:07 -0300 Subject: The GUI's idle wakeup copies no 20 KB message batch Queue.take built its batch (queue capacity plus room, some 20 KB) and returned it by value on every wakeup, a memset and a memcpy of it though the queue was empty; it led the idle profile. drainQueue now fills a batch the Shell keeps, and an empty queue leaves it untouched. Co-Authored-By: Claude Opus 5.5 --- src/gui/gui.zig | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/gui') diff --git a/src/gui/gui.zig b/src/gui/gui.zig index d935b5fd..e110b3ab 100644 --- a/src/gui/gui.zig +++ b/src/gui/gui.zig @@ -1061,9 +1061,19 @@ const Queue = struct { } fn take(q: *Queue) MessageBatch { + var batch: MessageBatch = .{}; + q.takeInto(&batch); + return batch; + } + + /// `take` into a batch the caller keeps: an idle wakeup copies nothing + /// (the batch is some 20 KB, and was built and returned by value each + /// time). + fn takeInto(q: *Queue, batch: *MessageBatch) void { + batch.len = 0; q.lock(); defer q.unlock(); - var batch: MessageBatch = .{}; + if (q.len == 0 and !q.files_changed and q.completion_len == 0) return; while (q.len > 0) { batch.items[batch.len] = q.items[q.head]; batch.len += 1; @@ -1080,7 +1090,6 @@ const Queue = struct { batch.len += q.completion_len; q.completion_len = 0; std.debug.assert(libc.pthread_cond_broadcast(&q.space) == .SUCCESS); - return batch; } fn discardCompletions(q: *Queue) void { @@ -3999,6 +4008,8 @@ const Shell = struct { ptys: *[pardes.MAX_PANES]?Pty, gens: *[pardes.MAX_PANES]u32, queue: *Queue, + /// What drainQueue takes each wakeup, kept rather than rebuilt. + batch: MessageBatch = .{}, pipe_tasks: *PipeTasks, inotify_fd: c_int, watches: *file_watch.Table, @@ -4153,7 +4164,8 @@ const Shell = struct { s.reconcilePtys(); // After this batch's output, which an exit is told behind. defer s.takeExits(); - var msgs = s.queue.take(); + s.queue.takeInto(&s.batch); + const msgs = &s.batch; var check_files = false; for (msgs.slice()) |m| switch (m) { .output => |o| { -- cgit v1.3