Add a proper public-facing documentation site using Mintlify with 19 MDX pages covering getting started, auto mode, commands, configuration, and all user-facing features. Move internal/SDK documentation (Pi SDK, TUI, context & hooks, research notes, ADRs) to docs-internal/ since they should not be part of the public documentation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1.8 KiB
1.8 KiB
Performance — Caching and Invalidation
The Caching Pattern
Always cache render() output and recompute only when state changes:
class CachedComponent {
private cachedWidth?: number;
private cachedLines?: string[];
render(width: number): string[] {
if (this.cachedLines && this.cachedWidth === width) {
return this.cachedLines;
}
// Expensive computation here
const lines = this.computeLines(width);
this.cachedWidth = width;
this.cachedLines = lines;
return lines;
}
invalidate(): void {
this.cachedWidth = undefined;
this.cachedLines = undefined;
}
}
The Update Cycle
State changes → invalidate() → tui.requestRender() → render(width) called
- Something changes your component's state (user input, timer, async result)
- Call
this.invalidate()to clear caches - Call
tui.requestRender()to schedule a re-render - The TUI calls
render(width)on the next frame - Your component recomputes its output (since cache was cleared)
Game Loop Pattern (Real-Time Updates)
class GameComponent {
private interval: ReturnType<typeof setInterval> | null = null;
private version = 0;
private cachedVersion = -1;
constructor(private tui: { requestRender: () => void }) {
this.interval = setInterval(() => {
this.tick();
this.version++;
this.tui.requestRender();
}, 100); // 10 FPS
}
render(width: number): string[] {
if (this.cachedVersion === this.version && /* width unchanged */) {
return this.cachedLines;
}
// ... render ...
this.cachedVersion = this.version;
return lines;
}
dispose(): void {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
}
}