c754984df8
Complete rewrite of the terminal pipeline for VS Code Server-level responsiveness. Key improvements: Backend: - Replace blocking select.select(0.1) with asyncio.add_reader() for event-driven PTY reading (eliminates ~110ms polling latency) - Add output batching (2ms window) to reduce WebSocket frame overhead - Add flow control: client acks processed bytes, server pauses PTY reads at 64KB threshold, resumes at 32KB - Add 5s ack timeout fallback to prevent stuck sessions Frontend: - Switch WebSocket to binary mode (binaryType = 'arraybuffer') - Eliminate Blob -> arrayBuffer async conversion overhead - Add flow control ack messages (every 4096 bytes or 100ms) - Add xterm-addon-webgl with graceful DOM fallback - Add performance tuning (scrollback=10000, fastScrollSensitivity) SDD artifacts: - openspec/explorations/terminal-responsiveness.md - openspec/proposals/terminal-responsiveness.md - openspec/specs/terminal-responsiveness.md - openspec/designs/terminal-responsiveness.md - openspec/tasks/terminal-responsiveness.md Quality gates: pytest (19 passed, 1 skipped), tsc --noEmit clean
3.3 KiB
3.3 KiB
Proposal: High-Performance Web Terminal
Status
Phase: proposal → spec → design → tasks → apply
Date: 2026-06-02
Owner: el Gentleman
Scope: Terminal I/O latency, rendering performance, connection stability
Problem
The current web terminal has noticeable latency on keystrokes, choppy scrolling, and poor performance during output bursts. Users report it feels "slow" compared to VS Code Server's terminal, which feels almost local.
Goals
| Metric | Current | Target | How Measured |
|---|---|---|---|
| Input latency (keypress → char visible) | ~110ms | < 16ms (1 frame) | term.write() timestamp diff |
Output throughput (cat /dev/zero) |
~200KB/s | > 1 MB/s | Bytes/sec over 5s |
| Resize latency | ~200ms | < 50ms | Time from resize msg to shell SIGWINCH |
| Reconnection + replay | ~2s | < 300ms | Time from WS open to first rendered char |
Frame drops during yes |
Many | 0 | requestAnimationFrame counter |
Non-Goals
- Changing the terminal UI/UX (chrome, controls, tabs)
- Adding new terminal features (search, multi-cursor, etc.)
- Changing authentication or session persistence model
- Supporting non-Docker container runtimes
Constraints
- Must work with existing tool instance lifecycle (docker containers)
- Must preserve WebSocket-based architecture
- Must preserve session persistence across reconnections
- Must work in both development and production compose setups
Solution Overview
Replace the blocking select.select() PTY read loop with asyncio-native event-driven I/O. Replace docker exec subprocess with Docker Engine API attach. Switch WebSocket to binary mode. Add output batching. Add WebGL renderer.
Key Decisions
- Keep
docker execfor now — Docker SDK attach doesn't support PTY mode as cleanly. We can optimize the subprocess approach with proper fd handling. - Use
asyncio.add_reader()— Native asyncio event-driven fd reading eliminates polling latency. - Binary WebSocket frames —
ws.binaryType = "arraybuffer"eliminates Blob conversion overhead. - WebGL renderer with DOM fallback — GPU acceleration where available, graceful fallback.
- Output batching with 2ms window — Collect small writes before sending to reduce frame overhead.
- Flow control v2 — Client acknowledges processed bytes; server pauses reads when buffer is full.
Risks
- Event loop blocking:
asyncio.add_reader()on a PTY fd may not work on all platforms (should work on Linux) - WebGL compatibility: Some GPUs/drivers may fail WebGL context creation
- Docker exec subprocess: Still adds overhead; may revisit Docker API attach in future
- Full rewrite: Large change surface; thorough testing required
Acceptance Criteria
- Input latency < 16ms measured with synthetic benchmark
- Output throughput > 1 MB/s measured with
cat /dev/zero - Resize latency < 50ms
- Reconnection + replay < 300ms
- No frame drops during
yescommand - All existing terminal tests pass
- WebGL renderer loads successfully on modern browsers
- Graceful fallback to DOM renderer if WebGL fails
- Flow control prevents memory bloat on
cat /dev/urandom | base64
Related
openspec/explorations/terminal-responsiveness.md— Detailed bottleneck analysis