From 4a13f06f516bdedc4f195e2d1fb8267e1d67616f Mon Sep 17 00:00:00 2001 From: Alexander Eichhorn Date: Wed, 4 Mar 2026 21:04:52 +0100 Subject: [PATCH] perf(canvas): detach hidden layers from DOM, throttle onscreen checks, increase cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - setVisibility now uses layer.remove()/stage.add() to detach/reattach hidden canvas elements from the DOM, freeing browser compositing resources - Wrap syncIsOnscreen and syncIntersectsBbox with rafThrottle to reduce redundant calculations during pan/zoom - Increase canvasElementCacheSize 32→128 and imageDataCacheSize 32→64 - Add 3-Layer-Flattening design document for future architectural optimization --- .../controlLayers/konva/CanvasCacheModule.ts | 4 ++-- .../CanvasEntity/CanvasEntityAdapterBase.ts | 22 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasCacheModule.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasCacheModule.ts index 40875ed78bc..d731ff766da 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasCacheModule.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasCacheModule.ts @@ -39,9 +39,9 @@ type CanvasCacheModuleConfig = { const DEFAULT_CONFIG: CanvasCacheModuleConfig = { imageNameCacheSize: 1000, - imageDataCacheSize: 32, + imageDataCacheSize: 64, transparencyCalculationCacheSize: 1000, - canvasElementCacheSize: 32, + canvasElementCacheSize: 128, generationModeCacheSize: 100, }; diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterBase.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterBase.ts index c733334ed09..3b9b4808322 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterBase.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasEntity/CanvasEntityAdapterBase.ts @@ -325,7 +325,7 @@ export abstract class CanvasEntityAdapterBase entity?.position); - syncIsOnscreen = () => { + syncIsOnscreen = rafThrottle(() => { const stageRect = this.manager.stage.getScaledStageRect(); const isOnScreen = this.checkIntersection(stageRect); const prevIsOnScreen = this.$isOnScreen.get(); @@ -334,9 +334,9 @@ export abstract class CanvasEntityAdapterBase { + syncIntersectsBbox = rafThrottle(() => { const bboxRect = this.manager.stateApi.getBbox().rect; const intersectsBbox = this.checkIntersection(bboxRect); const prevIntersectsBbox = this.$intersectsBbox.get(); @@ -344,7 +344,7 @@ export abstract class CanvasEntityAdapterBase { const entityRect = this.transformer.$pixelRect.get(); @@ -526,8 +526,13 @@ export abstract class CanvasEntityAdapterBase