⚡ Reduce commit cost when dropping large selections (#12032)

Collect children ids into one transient vector and track WASM shape
changes in a JS Map instead of a volatile persistent map.

AI-assisted-by: claude-opus-5-5
This commit is contained in:
Elena Torró 2026-10-02 11:22:19 +02:00 committed by GitHub
parent 3a0ed93360
commit 13a9da3bc3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 14 deletions

View File

@ -162,14 +162,15 @@
([objects id {:keys [ignore-children-fn] ([objects id {:keys [ignore-children-fn]
;;ignore-children-fn should receive a shape and return a boolean ;;ignore-children-fn should receive a shape and return a boolean
:or {ignore-children-fn (constantly false)}}] :or {ignore-children-fn (constantly false)}}]
(letfn [(get-children-ids-rec [id processed] (letfn [(collect [result id processed]
(when-not (contains? processed id) (if (contains? processed id)
(when-let [shapes (as-> (get objects id) $ result
(:shapes $) (let [shapes (into [] (remove ignore-children-fn) (dm/get-in objects [id :shapes]))
(remove ignore-children-fn $) processed (conj processed id)]
(some-> $ vec))] (reduce #(collect %1 %2 processed)
(into shapes (mapcat #(get-children-ids-rec % (conj processed id))) shapes))))] (reduce conj! result shapes)
(get-children-ids-rec id #{})))) shapes))))]
(persistent! (collect (transient []) id #{})))))
(defn get-children-ids-with-self (defn get-children-ids-with-self
[objects id] [objects id]

View File

@ -133,14 +133,14 @@
(if (and (not ignore-wasm?) (features/active-feature? state "render-wasm/v1")) (if (and (not ignore-wasm?) (features/active-feature? state "render-wasm/v1"))
;; Update the wasm model ;; Update the wasm model
(let [shape-changes (volatile! {}) (let [shape-changes (js/Map.)
state state
(binding [cts/*shape-changes* shape-changes] (binding [cts/*shape-changes* shape-changes]
(update-in state [:files file-id :data] apply-changes))] (update-in state [:files file-id :data] apply-changes))]
(let [objects (dm/get-in state [:files file-id :data :pages-index (:current-page-id state) :objects])] (let [objects (dm/get-in state [:files file-id :data :pages-index (:current-page-id state) :objects])]
(wasm.shape/process-shape-changes! objects @shape-changes)) (wasm.shape/process-shape-changes! objects (es6-iterator-seq (.entries shape-changes))))
state) state)

View File

@ -348,10 +348,15 @@
;; `conj` empty set initialization ;; `conj` empty set initialization
(def conj* (fnil conj (d/ordered-set))) (def conj* (fnil conj (d/ordered-set)))
(defn- track-change!
[self k]
(when-let [changes shape/*shape-changes*]
(let [id (:id self)]
(.set changes id (conj* (.get changes id) k)))))
(defn- impl-assoc (defn- impl-assoc
[self k v] [self k v]
(when shape/*shape-changes* (track-change! self k)
(vswap! shape/*shape-changes* update (:id self) conj* k))
(case k (case k
:id :id
@ -379,8 +384,7 @@
(defn- impl-dissoc (defn- impl-dissoc
[self k] [self k]
(when shape/*shape-changes* (track-change! self k)
(vswap! shape/*shape-changes* update (:id self) conj* k))
(case k (case k
:id :id