From 3ca0a32a1487823b3091ff3f6bb9260473aef57e Mon Sep 17 00:00:00 2001 From: Dariusz L Date: Thu, 26 Jun 2025 19:18:05 +0200 Subject: [PATCH] Add operation-based auto garbage collection for images Introduces an operation counter and threshold in ImageReferenceManager to trigger automatic garbage collection after a set number of canvas operations. Canvas now increments the operation count on save, undo, and redo, and exposes methods to set the operation threshold and retrieve stats including operation count. CanvasView displays the operation count and threshold after manual garbage collection. --- js/Canvas.js | 28 +++++++++++++++++++++++++- js/CanvasView.js | 2 +- js/ImageReferenceManager.js | 40 ++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/js/Canvas.js b/js/Canvas.js index 08d95e5..0a6b382 100644 --- a/js/Canvas.js +++ b/js/Canvas.js @@ -78,14 +78,17 @@ export class Canvas { saveState(replaceLast = false) { this.canvasState.saveState(replaceLast); + this.incrementOperationCount(); } undo() { this.canvasState.undo(); + this.incrementOperationCount(); } redo() { this.canvasState.redo(); + this.incrementOperationCount(); } updateSelectionAfterHistory() { @@ -376,6 +379,15 @@ export class Canvas { return this.canvasLayers.showOpacitySlider(mode); } + /** + * Zwiększa licznik operacji (wywoływane przy każdej operacji na canvas) + */ + incrementOperationCount() { + if (this.imageReferenceManager) { + this.imageReferenceManager.incrementOperationCount(); + } + } + /** * Ręczne uruchomienie garbage collection */ @@ -390,11 +402,25 @@ export class Canvas { */ getGarbageCollectionStats() { if (this.imageReferenceManager) { - return this.imageReferenceManager.getStats(); + const stats = this.imageReferenceManager.getStats(); + return { + ...stats, + operationCount: this.imageReferenceManager.operationCount, + operationThreshold: this.imageReferenceManager.operationThreshold + }; } return null; } + /** + * Ustawia próg operacji dla automatycznego GC + */ + setGarbageCollectionThreshold(threshold) { + if (this.imageReferenceManager) { + this.imageReferenceManager.setOperationThreshold(threshold); + } + } + /** * Czyści zasoby canvas (wywoływane przy usuwaniu) */ diff --git a/js/CanvasView.js b/js/CanvasView.js index f494d9c..b18835e 100644 --- a/js/CanvasView.js +++ b/js/CanvasView.js @@ -681,7 +681,7 @@ async function createCanvasWidget(node, widget, app) { const newStats = canvas.getGarbageCollectionStats(); log.info("GC Stats after cleanup:", newStats); - alert(`Garbage collection completed!\nTracked images: ${newStats.trackedImages}\nTotal references: ${newStats.totalReferences}`); + alert(`Garbage collection completed!\nTracked images: ${newStats.trackedImages}\nTotal references: ${newStats.totalReferences}\nOperations: ${newStats.operationCount}/${newStats.operationThreshold}`); } catch (e) { log.error("Failed to run garbage collection:", e); alert("Error running garbage collection. Check the console for details."); diff --git a/js/ImageReferenceManager.js b/js/ImageReferenceManager.js index 9e2f78d..685f047 100644 --- a/js/ImageReferenceManager.js +++ b/js/ImageReferenceManager.js @@ -13,7 +13,11 @@ export class ImageReferenceManager { this.gcTimer = null; this.isGcRunning = false; - // Nie uruchamiamy automatycznego GC + // Licznik operacji dla automatycznego GC + this.operationCount = 0; + this.operationThreshold = 500; // Uruchom GC po 500 operacjach + + // Nie uruchamiamy automatycznego GC na czasie // this.startGarbageCollection(); } @@ -241,6 +245,40 @@ export class ImageReferenceManager { } } + /** + * Zwiększa licznik operacji i sprawdza czy uruchomić GC + */ + incrementOperationCount() { + this.operationCount++; + log.debug(`Operation count: ${this.operationCount}/${this.operationThreshold}`); + + if (this.operationCount >= this.operationThreshold) { + log.info(`Operation threshold reached (${this.operationThreshold}), triggering garbage collection`); + this.operationCount = 0; // Reset counter + // Uruchom GC asynchronicznie, żeby nie blokować operacji + setTimeout(() => { + this.performGarbageCollection(); + }, 100); + } + } + + /** + * Resetuje licznik operacji + */ + resetOperationCount() { + this.operationCount = 0; + log.debug("Operation count reset"); + } + + /** + * Ustawia próg operacji dla automatycznego GC + * @param {number} threshold - Nowy próg operacji + */ + setOperationThreshold(threshold) { + this.operationThreshold = Math.max(1, threshold); + log.info(`Operation threshold set to: ${this.operationThreshold}`); + } + /** * Ręczne uruchomienie garbage collection */