Fix TUI performance regression: add caching to Box, use Text directly for built-in tools

This commit is contained in:
Mario Zechner 2025-12-17 16:39:23 +01:00
parent 48b481eb85
commit 909989066a
13 changed files with 173 additions and 99 deletions

View file

@ -10,6 +10,12 @@ export class Box implements Component {
private paddingY: number;
private bgFn?: (text: string) => string;
// Cache for rendered output
private cachedWidth?: number;
private cachedChildLines?: string;
private cachedBgSample?: string;
private cachedLines?: string[];
constructor(paddingX = 1, paddingY = 1, bgFn?: (text: string) => string) {
this.paddingX = paddingX;
this.paddingY = paddingY;
@ -18,24 +24,36 @@ export class Box implements Component {
addChild(component: Component): void {
this.children.push(component);
this.invalidateCache();
}
removeChild(component: Component): void {
const index = this.children.indexOf(component);
if (index !== -1) {
this.children.splice(index, 1);
this.invalidateCache();
}
}
clear(): void {
this.children = [];
this.invalidateCache();
}
setBgFn(bgFn?: (text: string) => string): void {
this.bgFn = bgFn;
// Don't invalidate here - we'll detect bgFn changes by sampling output
}
private invalidateCache(): void {
this.cachedWidth = undefined;
this.cachedChildLines = undefined;
this.cachedBgSample = undefined;
this.cachedLines = undefined;
}
invalidate(): void {
this.invalidateCache();
for (const child of this.children) {
child.invalidate?.();
}
@ -62,6 +80,20 @@ export class Box implements Component {
return [];
}
// Check if bgFn output changed by sampling
const bgSample = this.bgFn ? this.bgFn("test") : undefined;
// Check cache validity
const childLinesKey = childLines.join("\n");
if (
this.cachedLines &&
this.cachedWidth === width &&
this.cachedChildLines === childLinesKey &&
this.cachedBgSample === bgSample
) {
return this.cachedLines;
}
// Apply background and padding
const result: string[] = [];
@ -80,6 +112,12 @@ export class Box implements Component {
result.push(this.applyBg("", width));
}
// Update cache
this.cachedWidth = width;
this.cachedChildLines = childLinesKey;
this.cachedBgSample = bgSample;
this.cachedLines = result;
return result;
}