From 66997d2bc9f9365b8e6b096bcb5fd1d09b2027dc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 16 Oct 2025 14:36:28 +0200 Subject: [PATCH] :sparkles: Add set_children granular methods for performance --- frontend/src/app/render_wasm/api.cljs | 72 ++++++++++++-- render-wasm/src/main.rs | 136 ++++++++++++++++++++++++-- 2 files changed, 190 insertions(+), 18 deletions(-) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 01c90b7ce1..a92abfd454 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -155,18 +155,72 @@ (defn set-shape-children [children] (perf/begin-measure "set-shape-children") - (when-not ^boolean (empty? children) + (case (count children) + 0 + (h/call wasm/internal-module "_set_children_0") + + 1 + (let [[c1] children + c1 (uuid/get-u32 c1)] + (h/call wasm/internal-module "_set_children_1" + (aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3))) + + 2 + (let [[c1 c2] children + c1 (uuid/get-u32 c1) + c2 (uuid/get-u32 c2)] + (h/call wasm/internal-module "_set_children_2" + (aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3) + (aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3))) + + 3 + (let [[c1 c2 c3] children + c1 (uuid/get-u32 c1) + c2 (uuid/get-u32 c2) + c3 (uuid/get-u32 c3)] + (h/call wasm/internal-module "_set_children_3" + (aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3) + (aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3) + (aget c3 0) (aget c3 1) (aget c3 2) (aget c3 3))) + + 4 + (let [[c1 c2 c3 c4] children + c1 (uuid/get-u32 c1) + c2 (uuid/get-u32 c2) + c3 (uuid/get-u32 c3) + c4 (uuid/get-u32 c4)] + (h/call wasm/internal-module "_set_children_4" + (aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3) + (aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3) + (aget c3 0) (aget c3 1) (aget c3 2) (aget c3 3) + (aget c4 0) (aget c4 1) (aget c4 2) (aget c4 3))) + + 5 + (let [[c1 c2 c3 c4 c5] children + c1 (uuid/get-u32 c1) + c2 (uuid/get-u32 c2) + c3 (uuid/get-u32 c3) + c4 (uuid/get-u32 c4) + c5 (uuid/get-u32 c5)] + (h/call wasm/internal-module "_set_children_5" + (aget c1 0) (aget c1 1) (aget c1 2) (aget c1 3) + (aget c2 0) (aget c2 1) (aget c2 2) (aget c2 3) + (aget c3 0) (aget c3 1) (aget c3 2) (aget c3 3) + (aget c4 0) (aget c4 1) (aget c4 2) (aget c4 3) + (aget c5 0) (aget c5 1) (aget c5 2) (aget c5 3))) + + ;; Dynamic call for children > 5 (let [heap (mem/get-heap-u32) size (mem/get-alloc-size children UUID-U8-SIZE) offset (mem/alloc->offset-32 size)] - (reduce (fn [offset id] - (mem.h32/write-uuid offset heap id)) - offset - children))) - - (let [result (h/call wasm/internal-module "_set_children")] - (perf/end-measure "set-shape-children") - result)) + (reduce + (fn [offset id] + (mem.h32/write-uuid offset heap id)) + offset + children) + (h/call wasm/internal-module "_set_children"))) + (perf/end-measure "set-shape-children") + nil) (defn- get-string-length [string] diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index a8b8bb036c..f2ab215147 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -287,15 +287,7 @@ pub extern "C" fn add_shape_child(a: u32, b: u32, c: u32, d: u32) { }); } -#[no_mangle] -pub extern "C" fn set_children() { - let bytes = mem::bytes_or_empty(); - - let entries: IndexSet = bytes - .chunks(size_of::<::BytesType>()) - .map(|data| Uuid::from_bytes(data.try_into().unwrap())) - .collect(); - +fn set_children_set(entries: IndexSet) { let mut deleted = IndexSet::new(); with_current_shape_mut!(state, |shape: &mut Shape| { @@ -308,6 +300,132 @@ pub extern "C" fn set_children() { state.delete_shape(id); } }); +} + +#[no_mangle] +pub extern "C" fn set_children_0() { + let entries = IndexSet::from_iter(vec![]); + set_children_set(entries); +} + +#[no_mangle] +pub extern "C" fn set_children_1(a1: u32, b1: u32, c1: u32, d1: u32) { + let entries = IndexSet::from_iter(vec![uuid_from_u32_quartet(a1, b1, c1, d1)]); + set_children_set(entries); +} + +#[no_mangle] +pub extern "C" fn set_children_2( + a1: u32, + b1: u32, + c1: u32, + d1: u32, + a2: u32, + b2: u32, + c2: u32, + d2: u32, +) { + let entries = IndexSet::from_iter(vec![ + uuid_from_u32_quartet(a1, b1, c1, d1), + uuid_from_u32_quartet(a2, b2, c2, d2), + ]); + set_children_set(entries); +} + +#[no_mangle] +pub extern "C" fn set_children_3( + a1: u32, + b1: u32, + c1: u32, + d1: u32, + a2: u32, + b2: u32, + c2: u32, + d2: u32, + a3: u32, + b3: u32, + c3: u32, + d3: u32, +) { + let entries = IndexSet::from_iter(vec![ + uuid_from_u32_quartet(a1, b1, c1, d1), + uuid_from_u32_quartet(a2, b2, c2, d2), + uuid_from_u32_quartet(a3, b3, c3, d3), + ]); + set_children_set(entries); +} + +#[no_mangle] +pub extern "C" fn set_children_4( + a1: u32, + b1: u32, + c1: u32, + d1: u32, + a2: u32, + b2: u32, + c2: u32, + d2: u32, + a3: u32, + b3: u32, + c3: u32, + d3: u32, + a4: u32, + b4: u32, + c4: u32, + d4: u32, +) { + let entries = IndexSet::from_iter(vec![ + uuid_from_u32_quartet(a1, b1, c1, d1), + uuid_from_u32_quartet(a2, b2, c2, d2), + uuid_from_u32_quartet(a3, b3, c3, d3), + uuid_from_u32_quartet(a4, b4, c4, d4), + ]); + set_children_set(entries); +} + +#[no_mangle] +pub extern "C" fn set_children_5( + a1: u32, + b1: u32, + c1: u32, + d1: u32, + a2: u32, + b2: u32, + c2: u32, + d2: u32, + a3: u32, + b3: u32, + c3: u32, + d3: u32, + a4: u32, + b4: u32, + c4: u32, + d4: u32, + a5: u32, + b5: u32, + c5: u32, + d5: u32, +) { + let entries = IndexSet::from_iter(vec![ + uuid_from_u32_quartet(a1, b1, c1, d1), + uuid_from_u32_quartet(a2, b2, c2, d2), + uuid_from_u32_quartet(a3, b3, c3, d3), + uuid_from_u32_quartet(a4, b4, c4, d4), + uuid_from_u32_quartet(a5, b5, c5, d5), + ]); + set_children_set(entries); +} + +#[no_mangle] +pub extern "C" fn set_children() { + let bytes = mem::bytes_or_empty(); + + let entries: IndexSet = bytes + .chunks(size_of::<::BytesType>()) + .map(|data| Uuid::from_bytes(data.try_into().unwrap())) + .collect(); + + set_children_set(entries); if !bytes.is_empty() { mem::free_bytes();