mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-12 23:01:21 +00:00
Addresses Issue #11705 Wave 0 Discovery acceptance criteria: - ADR: Node.js-first with opt-in Bun experimental strategy - Feature parity matrix: 54 items cataloged across Ink components, hooks, and tools - Performance baseline: startup, latency, render cadence, memory benchmarks - Implementation plan: 8-week roadmap across 60 tasks in 5 waves - Terminal compatibility matrix for cross-platform validation
170 lines
7 KiB
Markdown
170 lines
7 KiB
Markdown
# CLI Performance Baseline: Ink UI
|
|
|
|
**Issue:** [#11705](https://github.com/RooCodeInc/Roo-Code/issues/11705)
|
|
**Date:** 2026-02-22
|
|
**Purpose:** Establish baseline performance metrics for the current Ink-based CLI UI to enable comparison with OpenTUI prototype.
|
|
|
|
## Methodology
|
|
|
|
Measurements should be taken on a standardized environment:
|
|
- **Hardware:** Modern laptop/desktop (Apple M-series or equivalent x86_64)
|
|
- **Node.js:** v22 LTS
|
|
- **Terminal:** iTerm2 (macOS), GNOME Terminal (Linux), Windows Terminal (Windows)
|
|
- **Measurement tool:** `process.hrtime.bigint()` instrumentation, `node --cpu-prof`, `node --heap-prof`
|
|
|
|
Each metric should be measured across 10 runs with the median reported.
|
|
|
|
## Metrics
|
|
|
|
### 1. Startup Time
|
|
|
|
Time from process start to first UI frame rendered.
|
|
|
|
| Metric | Description | Target Measurement |
|
|
|--------|-------------|-------------------|
|
|
| Cold start | First run after clearing module cache | `process.hrtime` from entry to first Ink `render()` call |
|
|
| Warm start | Subsequent runs with module cache | Same as above |
|
|
| TTY detection | Time to determine TUI vs non-TUI mode | `run.ts` TTY check to renderer selection |
|
|
| React hydration | Time for React/Ink to initialize component tree | Ink `render()` call to first `useEffect` fire |
|
|
|
|
**Expected baseline (Ink):**
|
|
- Cold start: ~300-500ms (includes module loading, React init, Ink renderer setup)
|
|
- Warm start: ~150-250ms
|
|
- TTY detection: <1ms (synchronous `process.stdin.isTTY` check)
|
|
|
|
### 2. Input Latency
|
|
|
|
Time from keypress to visible UI update.
|
|
|
|
| Metric | Description | Target Measurement |
|
|
|--------|-------------|-------------------|
|
|
| Single character | Typing a character in the input field | Keypress event to re-render completion |
|
|
| Backspace | Deleting a character | Same as above |
|
|
| Cursor navigation | Arrow key movement | Keypress to cursor position update |
|
|
| Autocomplete trigger | Typing `@` or `/` to open autocomplete | Keypress to picker display |
|
|
| Autocomplete selection | Selecting an item from picker | Enter key to picker close + text insert |
|
|
|
|
**Expected baseline (Ink):**
|
|
- Single character input: ~8-16ms (Ink batches renders at ~60fps)
|
|
- Autocomplete trigger: ~16-32ms (state update + picker render)
|
|
- Selection: ~16ms (state update + re-render)
|
|
|
|
### 3. Render Cadence
|
|
|
|
Frame timing for continuous updates (e.g., streaming AI responses).
|
|
|
|
| Metric | Description | Target Measurement |
|
|
|--------|-------------|-------------------|
|
|
| Idle render rate | Renders per second when no updates | Should be 0 (Ink only renders on state change) |
|
|
| Streaming render rate | Renders per second during message streaming | Ink throttled to ~30fps by default |
|
|
| Scroll render rate | Renders during scroll through history | Depends on `ScrollArea` implementation |
|
|
| Max render time | Longest single render cycle | `console.time` around render function |
|
|
|
|
**Expected baseline (Ink):**
|
|
- Idle: 0 renders/sec (event-driven)
|
|
- Streaming: ~15-30 renders/sec (Ink's internal throttle)
|
|
- Scroll: ~30 renders/sec
|
|
- Max render time: <16ms for typical content, <50ms for large message histories
|
|
|
|
### 4. Memory Usage
|
|
|
|
Heap consumption across different UI states.
|
|
|
|
| Metric | Description | Target Measurement |
|
|
|--------|-------------|-------------------|
|
|
| Baseline heap | Memory after initial render with empty chat | `process.memoryUsage().heapUsed` |
|
|
| After 10 messages | Heap after 10 chat messages rendered | Same |
|
|
| After 100 messages | Heap after 100 chat messages with scroll | Same |
|
|
| Peak heap | Maximum heap during heavy rendering | `--max-old-space-size` monitoring |
|
|
| GC pressure | Frequency and duration of garbage collection | `--trace-gc` flag |
|
|
|
|
**Expected baseline (Ink):**
|
|
- Baseline heap: ~30-50MB (React + Ink + Zustand + component tree)
|
|
- After 10 messages: ~40-60MB
|
|
- After 100 messages: ~60-100MB (depends on message content size)
|
|
- Peak heap: ~80-120MB during rapid streaming
|
|
|
|
### 5. Bundle Size
|
|
|
|
Size of the built CLI artifact.
|
|
|
|
| Metric | Description | Target Measurement |
|
|
|--------|-------------|-------------------|
|
|
| Total bundle | Size of `dist/index.js` | `ls -la dist/index.js` |
|
|
| Ink dependency tree | Size of ink + react + @inkjs/ui in node_modules | `du -sh` on relevant directories |
|
|
| UI-specific code | Size of `apps/cli/src/ui/` source | `find ... -exec wc -c` |
|
|
|
|
**Current measurements:**
|
|
- UI source: 69 files, 10,619 LOC
|
|
- Key dependencies: `ink` (6.6.0), `react` (19.1.0), `@inkjs/ui` (2.0.0), `zustand` (5.0.0)
|
|
|
|
## Instrumentation Plan
|
|
|
|
To collect these metrics, the following instrumentation should be added:
|
|
|
|
### Phase 1: Non-invasive (no code changes)
|
|
|
|
```bash
|
|
# Startup time
|
|
time node dist/index.js --help
|
|
|
|
# Memory baseline
|
|
node --expose-gc --max-old-space-size=256 dist/index.js --print "hello"
|
|
|
|
# CPU profile
|
|
node --cpu-prof dist/index.js --print "hello"
|
|
|
|
# Heap snapshot
|
|
node --heap-prof dist/index.js --print "hello"
|
|
```
|
|
|
|
### Phase 2: Instrumented (minimal code changes)
|
|
|
|
Add timing markers at key points in the render pipeline:
|
|
|
|
1. `run.ts` -- Process start timestamp
|
|
2. `App.tsx` -- First render timestamp (via `useEffect`)
|
|
3. `MultilineTextInput.tsx` -- Input event to render completion
|
|
4. `ScrollArea.tsx` -- Scroll render timing
|
|
5. `ChatHistoryItem.tsx` -- Message render timing
|
|
|
|
### Phase 3: Automated benchmark suite
|
|
|
|
Create a benchmark script that:
|
|
1. Launches the CLI in TUI mode with a mock backend
|
|
2. Simulates keypress sequences
|
|
3. Records render timings via process instrumentation
|
|
4. Outputs a JSON report for comparison
|
|
|
|
## Terminal Compatibility Matrix
|
|
|
|
| Terminal | OS | ANSI Support | 256 Color | True Color | Unicode | Mouse | Notes |
|
|
|----------|-----|-------------|-----------|------------|---------|-------|-------|
|
|
| iTerm2 | macOS | Full | Yes | Yes | Yes | Yes | Primary dev terminal |
|
|
| Terminal.app | macOS | Full | Yes | Limited | Yes | No | Default macOS terminal |
|
|
| GNOME Terminal | Linux | Full | Yes | Yes | Yes | Yes | Default Ubuntu/GNOME |
|
|
| Windows Terminal | Windows | Full | Yes | Yes | Yes | Yes | Modern Windows default |
|
|
| tmux | Cross-platform | Full | Yes | Varies | Yes | Yes | Needs `TERM=xterm-256color` |
|
|
| VS Code Terminal | Cross-platform | Full | Yes | Yes | Yes | Yes | Common dev environment |
|
|
| Alacritty | Cross-platform | Full | Yes | Yes | Yes | Yes | GPU-accelerated |
|
|
| Warp | macOS | Full | Yes | Yes | Yes | Yes | Modern terminal |
|
|
|
|
### Known Issues
|
|
|
|
- **tmux:** True color support requires `set -g default-terminal "tmux-256color"` in tmux.conf
|
|
- **Terminal.app:** No true color support; falls back to 256 color palette
|
|
- **Older Windows cmd.exe:** Not supported (use Windows Terminal instead)
|
|
- **SSH sessions:** Terminal capabilities depend on client terminal, not server
|
|
|
|
## Comparison Framework
|
|
|
|
When OpenTUI prototype is ready, compare using this template:
|
|
|
|
| Metric | Ink Baseline | OpenTUI Prototype | Delta | Notes |
|
|
|--------|-------------|-------------------|-------|-------|
|
|
| Cold start | ___ ms | ___ ms | ___% | |
|
|
| Warm start | ___ ms | ___ ms | ___% | |
|
|
| Input latency | ___ ms | ___ ms | ___% | |
|
|
| Streaming FPS | ___ fps | ___ fps | ___% | |
|
|
| Baseline heap | ___ MB | ___ MB | ___% | |
|
|
| Bundle size | ___ MB | ___ MB | ___% | |
|