Skip to content

Implement partial rendering for TUI performance optimization #109

Description

@travisennis

Summary

Currently, the TUI implementation in `source/tui/tui.ts` uses full-screen re-rendering for every update, which is simple but potentially inefficient for large outputs or frequent updates. The Pi-Mono project has a sophisticated partial rendering implementation that could be adopted to improve performance.

Current Implementation

The ACAI TUI (`source/tui/tui.ts`) uses a full re-render approach:

  • Always clears entire screen with `\x1b[3J\x1b[2J\x1b[H`
  • Renders all components from scratch on every update
  • No previous state tracking
  • Comment explicitly states: 'always do full re-render for simplicity and reliability'

Proposed Changes

Adopt the partial rendering approach from Pi-Mono's TUI implementation.

1. Component Interface Update

Add `invalidate(): void` method:
```typescript
interface Component {
render(width: number): string[];
handleInput?(data: string): void;
invalidate(): void; // NEW
}
```

2. State Tracking

Add to TUI class:
```typescript
private previousLines: string[] = [];
private previousWidth = 0;
private cursorRow = 0; // Track cursor position
```

3. Differential Rendering Logic

Implement:

  • Compare old vs new lines to find first changed line
  • Only update lines from first change to end
  • Viewport-aware optimization (if change is outside viewport, full re-render)
  • Use `\x1b[2K` for line clearing instead of `\x1b[J`
  • Cursor positioning for partial updates

4. Rendering Pipeline

  • Track cursor position across renders
  • Handle width changes (trigger full re-render)
  • Maintain synchronized output for atomic updates
  • Add crash logging for debug (optional)

Implementation Complexity

Estimated Effort: 6-10 hours

  • Easy (1-2 hours): Interface and state tracking
  • Medium (3-4 hours): Differential rendering logic
  • Testing (2-3 hours): Edge cases and validation

Benefits

  • Performance: Only update changed lines instead of full screen
  • Reduced Flicker: More precise updates avoid full screen clears
  • Better UX: Smoother rendering for frequent updates
  • Scalability: Better performance with large outputs

Risks

  • Visual Artifacts: Incorrect partial updates could leave stale content
  • Cursor Position Bugs: Complex cursor tracking across partial updates
  • Edge Cases: Empty renders, width changes, boundary conditions

Testing Requirements

  • Verify correctness with various output sizes
  • Test cursor positioning accuracy
  • Validate viewport boundary handling
  • Performance benchmarking

Reference Implementation

Pi-Mono TUI: /Users/travisennis/Github/code-agents/pi-mono/packages/tui/src/tui.ts

Key features to port:

  • Differential line comparison
  • Viewport-aware optimization
  • Cursor position tracking
  • Image line detection
  • Cell size querying

When to Consider This

Implement if:

  • Performance issues with large outputs
  • Frequent small updates (typing, animations)
  • User reports of flicker or slow rendering

Defer if:

  • Current performance is acceptable
  • Simplicity and reliability are priorities
  • Limited testing resources

Next Steps

  1. Review Pi-Mono implementation for detailed approach
  2. Create implementation plan with incremental milestones
  3. Add comprehensive tests for edge cases
  4. Performance benchmark before/after
  5. Update all components to implement `invalidate()` method

Acceptance Criteria

  • Partial rendering implemented with differential updates
  • All existing tests pass
  • No visual artifacts or stale content
  • Cursor positioning works correctly
  • Performance benchmarks show improvement
  • All components implement `invalidate()` method
  • Viewport optimization working correctly

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions