Skip to content

[perf] Terminal stream events lack client-side batching before xterm.write() #2241

Closed as duplicate

Description

@tt-a1i

Problem

The backend PTY output is well-batched at ~30Hz (pty-subprocess.ts, 32ms flush interval with 128KB cap). However, on the renderer side, each stream event from the tRPC subscription calls xterm.write() individually without further batching:

// Terminal.tsx line 262-268
electronTrpc.terminal.stream.useSubscription(paneId, {
  onData: (event) => {
    handleStreamData(event);  // writes to xterm per-message
  },
});

When agents produce rapid output (Codex streaming, Claude Code tool results, npm install logs), the renderer processes each IPC message as a separate xterm.write() call. Each call can trigger:

  • xterm parser processing
  • WebGL texture atlas updates
  • Potential layout recalculations

Native terminals batch rendering at the display refresh rate. xterm.js does have internal write buffering, but coalescing writes before they enter xterm's pipeline would reduce overhead further.

Suggested Fix

Add a client-side write coalescing buffer using requestAnimationFrame:

const pendingWrites = useRef<string[]>([]);
const rafScheduled = useRef(false);

function scheduleWrite(data: string) {
  pendingWrites.current.push(data);
  if (!rafScheduled.current) {
    rafScheduled.current = true;
    requestAnimationFrame(() => {
      const batch = pendingWrites.current.join("");
      pendingWrites.current = [];
      rafScheduled.current = false;
      xterm.write(batch);
    });
  }
}

This coalesces all writes arriving within a single frame into one xterm.write() call, aligned with the display refresh rate.

Environment

  • Superset 1.1.2
  • macOS

Activity

  1. added 2 commits that reference this issue on Mar 8, 2026
  2. Kitenite commented on Jul 11, 2026

    @Kitenite
    Member

    Closing as a duplicate of #5602, the consolidated tracker for stale performance issues from the July 2026 stale-issue sweep (no activity since 2026-06-01). If this still applies on a current build, comment on #5602 and we'll reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions