From 7fa225115ef6b6b33e0ecadb99fcf92adb80eedb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Torr=C3=B3?= Date: Fri, 6 Nov 2026 11:33:37 +0100 Subject: [PATCH] :zap: Reuse uuid instances when decoding transit on the frontend (#12792) --- common/src/app/common/transit.cljc | 33 ++++++++++++++++++++++- frontend/src/app/main/data/workspace.cljs | 2 ++ frontend/src/app/worker/index.cljs | 2 ++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/common/src/app/common/transit.cljc b/common/src/app/common/transit.cljc index 41b503316f..5e205144ba 100644 --- a/common/src/app/common/transit.cljc +++ b/common/src/app/common/transit.cljc @@ -110,6 +110,37 @@ (.set cache value kw) kw)))))) +#?(:cljs + (def ^:private uuid-cache-size + "Twice the ids of a very large page (~60k shapes), so decoding one + page does not rotate the cache." + 131072)) + +#?(:cljs (def ^:private recent-uuids (js/Map.))) +#?(:cljs (def ^:private previous-uuids (js/Map.))) + +#?(:cljs + (defn clear-uuid-cache + "Forget the cached uuids, so the ids of a closed file can be freed." + [] + (set! recent-uuids (js/Map.)) + (set! previous-uuids (js/Map.)))) + +#?(:cljs + (defn- read-uuid + "Give the same uuid instance for each value. Entries live in two + generations: when the recent one is full it becomes the previous one + and the older one is dropped, so the cache stays bounded." + [value] + (or (.get recent-uuids value) + (let [id (or (.get previous-uuids value) + (parse-uuid value))] + (when (>= (.-size recent-uuids) uuid-cache-size) + (set! previous-uuids recent-uuids) + (set! recent-uuids (js/Map.))) + (.set recent-uuids value id) + id)))) + (add-handlers! #?@(:clj [{:id "file" @@ -128,7 +159,7 @@ #?(:cljs {:id "u" - :rfn parse-uuid}) + :rfn read-uuid}) #?(:cljs {:id ":" diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f9bae33c38..7581866dc6 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -21,6 +21,7 @@ [app.common.math :as mth] [app.common.path-names :as cpn] [app.common.render-wasm.wasm :as wasm-state] + [app.common.transit :as t] [app.common.types.component :as ctc] [app.common.types.components-list :as ctkl] [app.common.types.shape :as cts] @@ -631,6 +632,7 @@ ptk/WatchEvent (watch [_ state _] + (t/clear-uuid-cache) (let [project-id (:current-project-id state)] (rx/of (dwn/finalize file-id) (dpj/finalize-project project-id) diff --git a/frontend/src/app/worker/index.cljs b/frontend/src/app/worker/index.cljs index 102b0b38d9..910fa74fae 100644 --- a/frontend/src/app/worker/index.cljs +++ b/frontend/src/app/worker/index.cljs @@ -12,6 +12,7 @@ [app.common.geom.rect :as grc] [app.common.logging :as log] [app.common.time :as ct] + [app.common.transit :as t] [app.worker.impl :as impl] [app.worker.selection :as selection] [app.worker.snap :as snap] @@ -78,6 +79,7 @@ (update :pages-index dissoc page-id) (update ::selection dissoc page-id) (update ::snap dissoc page-id))) + (t/clear-uuid-cache) (log/dbg :hint "page index dropped" :id page-id ::log/sync? true) nil)