TUI input and scrolling degrade in long sessions due to render-path work and mixed terminal readers
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 19.9k
- Forks
- 2.3k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 30
Description
Summary
Terminal interactivity can degrade substantially in longer Jcode sessions. Typing becomes delayed, mouse-wheel scrolling causes excessive redraw work, and fragmented mouse reports can appear as text in the composer.
I reproduced this on macOS using a real PTY. The underlying problems are in shared Jcode TUI code rather than macOS-specific application code.
Symptoms
• Input latency grows as the conversation becomes longer.
• Scrolling can cause large bursts of terminal output and high CPU usage.
• Input may fall back to redraw-tick latency instead of waking immediately.
• Mouse-wheel bursts can trigger a full repaint for every packet.
• Raw SGR mouse fragments such as [<65;50;24M can leak into the composer.
Reproduction evidence
On the broken build, a real PTY input probe missed 32 of 40 keystrokes and had approximately 169 ms median latency.
With the proposed fix:
• 40 of 40 keystrokes were delivered.
• Median latency was 0.254 ms.
• P95 latency was 0.438 ms.
• Under eight CPU burners, all 40 keystrokes were still delivered.
• A 96-byte burst completed in 0.635 ms with only three draws.
The severity depends on terminal timing and conversation size, but the problematic code paths are deterministic.
Root causes
The investigation found three independent causes:
-
Cache-hit telemetry performed transcript-linear byte estimation during rendering. This turns a nominal cache hit into work proportional to conversation size.
-
Memory sidecar discovery performed credential and model resolution on the render path.
-
Jcode mixed Crossterm’s asynchronous EventStream with synchronous poll and read calls. This violates Crossterm’s single-reader requirement and can split terminal packets. Removing the synchronous drain without replacing its coalescing also caused one full repaint per queued wheel or keyboard event.
The input reader also needed to preserve partially consumed Escape sequences across cancellation inside Tokio select calls. Otherwise a redraw or bus event could cancel the read and lose part of the terminal packet.
Proposed fix
I prepared an isolated branch with three commits:
https://github.com/apierron/jcode/tree/fix/tui-terminal-interactivity-lag
Comparison against upstream:
https://github.com/1jehuang/jcode/compare/master…apierron:fix/tui-terminal-interactivity-lag
Commits:
• be511853: Keep cache-hit metrics constant-time.
• f057724a: Move sidecar discovery off the render path.
• 8c530734: Use one bounded, cancellation-safe terminal reader and coalesce ready input before redrawing.
The branch changes only TUI code, adds no dependencies, and separates the three root causes into independent commits.
Validation
• Eight terminal-reader tests pass, covering ordering, cancellation, Escape deadlines, bounded lossless backpressure, prompt wakeups, coalescing, and task shutdown.
• Three focused render-path and cache tests pass.
• Formatting, Cargo check, and the Jcode TUI build pass.
• The changed files match the previously runtime-tested build.
• An independent review found no blocking correctness or scope issues.
• The full TUI suite still has existing environment and global-state failures, but the fix branch introduces no branch-only failures compared with the same suite on upstream master.
Platform scope
This was reproduced on macOS, but most of the problem is not macOS-specific:
• Transcript-linear cache work is platform-independent.
• Blocking sidecar discovery during rendering is platform-independent.
• The mixed-reader violation exists in shared, non-platform-gated Jcode code.
• Fragmented SGR mouse reports are a Unix and Crossterm behavior, so the raw mouse-text symptom is most likely on macOS and Linux.
• Terminal implementation and OS scheduling can change how severe the lag appears.
I have not run the final branch through equivalent real-terminal measurements on Linux or Windows, so identical reproduction there is not yet confirmed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the three commits on the linked fix/tui-terminal-interactivity-lag branch, then run the eight terminal-reader tests and the focused render-path and cache tests described in the issue. Done means preserving prompt responsiveness and input ordering, coalescing redraws, keeping render-path work bounded, and passing formatting, Cargo check, and the TUI build.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, performance, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100