mirror of
https://github.com/penpot/penpot.git
synced 2025-07-13 18:47:17 +02:00
♻️ Refactor some allocations
This commit is contained in:
parent
4f7d97a31e
commit
8922e7454f
9 changed files with 183 additions and 12 deletions
|
@ -778,7 +778,13 @@
|
||||||
(defn set-objects
|
(defn set-objects
|
||||||
[objects]
|
[objects]
|
||||||
(perf/begin-measure "set-objects")
|
(perf/begin-measure "set-objects")
|
||||||
(let [shapes (into [] (vals objects))
|
#_(do
|
||||||
|
(api-js/setObjects objects set-object)
|
||||||
|
(clear-drawing-cache)
|
||||||
|
(request-render "set-objects")
|
||||||
|
(perf/end-measure "set-objects"))
|
||||||
|
(let [get-memory-measure (perf/memory-measure)
|
||||||
|
shapes (into [] (vals objects))
|
||||||
total-shapes (count shapes)
|
total-shapes (count shapes)
|
||||||
pending
|
pending
|
||||||
(loop [index 0 pending []]
|
(loop [index 0 pending []]
|
||||||
|
@ -786,7 +792,8 @@
|
||||||
(let [shape (nth shapes index)
|
(let [shape (nth shapes index)
|
||||||
pending' (set-object objects shape)]
|
pending' (set-object objects shape)]
|
||||||
(recur (inc index) (into pending pending')))
|
(recur (inc index) (into pending pending')))
|
||||||
pending))]
|
pending))
|
||||||
|
_ (js/console.log (clj->js (get-memory-measure)))]
|
||||||
(perf/end-measure "set-objects")
|
(perf/end-measure "set-objects")
|
||||||
(clear-drawing-cache)
|
(clear-drawing-cache)
|
||||||
(request-render "set-objects")
|
(request-render "set-objects")
|
||||||
|
|
7
frontend/src/app/render_wasm/api.js
Normal file
7
frontend/src/app/render_wasm/api.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export function setObject(object) {
|
||||||
|
console.log(object.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setObjects(objects, fn) {
|
||||||
|
objects.forEach((object) => fn(objects, object))
|
||||||
|
}
|
|
@ -14,6 +14,35 @@
|
||||||
#?(:clj (= (System/getProperty "penpot.wasm.profile-marks") "true")
|
#?(:clj (= (System/getProperty "penpot.wasm.profile-marks") "true")
|
||||||
:cljs false))
|
:cljs false))
|
||||||
|
|
||||||
|
(defn create-memory
|
||||||
|
[used total]
|
||||||
|
#?(:clj {:used used :total total}
|
||||||
|
:cljs #js {:used used :total total}))
|
||||||
|
|
||||||
|
(defn get-memory
|
||||||
|
[]
|
||||||
|
#?(:clj (create-memory -1 -1)
|
||||||
|
:cljs (create-memory
|
||||||
|
(.-usedJSHeapSize (.-memory js/performance))
|
||||||
|
(.-totalJSHeapSize (.-memory js/performance)))))
|
||||||
|
|
||||||
|
(defn memory-measure
|
||||||
|
[]
|
||||||
|
#?(:clj (fn []
|
||||||
|
{:begin (create-memory -1 -1)
|
||||||
|
:end (create-memory -1 -1)
|
||||||
|
:delta (create-memory -1 -1)})
|
||||||
|
:cljs (let [begin-memory (get-memory)]
|
||||||
|
(fn []
|
||||||
|
(let [end-memory (get-memory)]
|
||||||
|
#js {:begin begin-memory
|
||||||
|
:end end-memory
|
||||||
|
:delta (create-memory
|
||||||
|
(- (.-used end-memory)
|
||||||
|
(.-used begin-memory))
|
||||||
|
(- (.-total end-memory)
|
||||||
|
(.-total begin-memory)))})))))
|
||||||
|
|
||||||
(defmacro begin-measure
|
(defmacro begin-measure
|
||||||
[measure-name]
|
[measure-name]
|
||||||
(when enabled?
|
(when enabled?
|
||||||
|
|
89
render-wasm/Cargo.lock
generated
89
render-wasm/Cargo.lock
generated
|
@ -49,6 +49,12 @@ version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.31"
|
version = "1.1.31"
|
||||||
|
@ -144,8 +150,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -211,6 +219,16 @@ version = "1.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "khronos_api"
|
name = "khronos_api"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
|
@ -293,6 +311,12 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
|
@ -395,6 +419,12 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
@ -558,6 +588,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
|
checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -566,6 +597,64 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
|
|
@ -7,7 +7,7 @@ license-file = "../LICENSE"
|
||||||
description = "Wasm-based canvas renderer for Penpot"
|
description = "Wasm-based canvas renderer for Penpot"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["profile"]
|
||||||
profile = ["profile-macros", "profile-raf"]
|
profile = ["profile-macros", "profile-raf"]
|
||||||
profile-macros = []
|
profile-macros = []
|
||||||
profile-raf = []
|
profile-raf = []
|
||||||
|
@ -26,7 +26,7 @@ skia-safe = { version = "0.81.0", default-features = false, features = [
|
||||||
"textlayout",
|
"textlayout",
|
||||||
"binary-cache",
|
"binary-cache",
|
||||||
] }
|
] }
|
||||||
uuid = { version = "1.11.0", features = ["v4"] }
|
uuid = { version = "1.11.0", features = ["v4", "js"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
|
|
@ -6,11 +6,30 @@ else
|
||||||
export _BUILD_MODE=${1:-debug};
|
export _BUILD_MODE=${1:-debug};
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 256 MB of initial heap to perform less
|
||||||
|
# initial calls to memory grow.
|
||||||
|
EM_INITIAL_HEAP=$((256 * 1024 * 1024))
|
||||||
|
|
||||||
|
# 1.0 doubles the heap on every growth.
|
||||||
|
EM_MEMORY_GROWTH_GEOMETRIC_STEP="0.8"
|
||||||
|
|
||||||
|
# Malloc implementation to use.
|
||||||
|
# - dlmalloc: a powerful general-purpose malloc.
|
||||||
|
# - emmalloc: a simple and compact malloc designed for emscripten.
|
||||||
|
# - emmalloc-debug: use emmalloc and add extra assertion checks.
|
||||||
|
# - emmalloc-memvalidate: use emmalloc with assertions+heap consistency checking.
|
||||||
|
# - emmalloc-verbose: use emmalloc with assertions + verbose logging.
|
||||||
|
# - emmalloc-memvalidate-verbose: use emmalloc with assertions + heap consistency checking + verbose logging.
|
||||||
|
# Default: dlmalloc
|
||||||
|
EM_MALLOC="dlmalloc"
|
||||||
|
|
||||||
EMCC_CFLAGS="--no-entry \
|
EMCC_CFLAGS="--no-entry \
|
||||||
--js-library src/js/wapi.js \
|
--js-library src/js/wapi.js \
|
||||||
-sASSERTIONS=1 \
|
-sASSERTIONS=1 \
|
||||||
-sALLOW_TABLE_GROWTH=1 \
|
-sALLOW_TABLE_GROWTH=1 \
|
||||||
-sALLOW_MEMORY_GROWTH=1 \
|
-sALLOW_MEMORY_GROWTH=1 \
|
||||||
|
-sINITIAL_HEAP=$EM_INITIAL_HEAP \
|
||||||
|
-sMEMORY_GROWTH_GEOMETRIC_STEP=$EM_MEMORY_GROWTH_GEOMETRIC_STEP \
|
||||||
-sENVIRONMENT=web \
|
-sENVIRONMENT=web \
|
||||||
-sERROR_ON_UNDEFINED_SYMBOLS=0 \
|
-sERROR_ON_UNDEFINED_SYMBOLS=0 \
|
||||||
-sMAX_WEBGL_VERSION=2 \
|
-sMAX_WEBGL_VERSION=2 \
|
||||||
|
@ -31,7 +50,7 @@ else
|
||||||
# -gseparate-dwarf
|
# -gseparate-dwarf
|
||||||
# -gsplit-dwarf
|
# -gsplit-dwarf
|
||||||
# -gsource-map
|
# -gsource-map
|
||||||
EMCC_CFLAGS="-g $EMCC_CFLAGS -sVERBOSE=1 -sMALLOC=emmalloc-debug"
|
EMCC_CFLAGS="-g $EMCC_CFLAGS -sVERBOSE=1 -sMALLOC=$EM_MALLOC"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export EMCC_CFLAGS;
|
export EMCC_CFLAGS;
|
||||||
|
|
|
@ -572,6 +572,9 @@ impl RenderState {
|
||||||
performance::end_measure!("tile_cache");
|
performance::end_measure!("tile_cache");
|
||||||
|
|
||||||
self.pending_nodes.clear();
|
self.pending_nodes.clear();
|
||||||
|
if self.pending_nodes.capacity() < tree.len() {
|
||||||
|
self.pending_nodes.reserve(tree.len() - self.pending_nodes.capacity());
|
||||||
|
}
|
||||||
// reorder by distance to the center.
|
// reorder by distance to the center.
|
||||||
self.current_tile = None;
|
self.current_tile = None;
|
||||||
self.render_in_progress = true;
|
self.render_in_progress = true;
|
||||||
|
|
|
@ -218,15 +218,15 @@ impl Shape {
|
||||||
constraint_h: None,
|
constraint_h: None,
|
||||||
constraint_v: None,
|
constraint_v: None,
|
||||||
clip_content: true,
|
clip_content: true,
|
||||||
fills: vec![],
|
fills: Vec::with_capacity(1),
|
||||||
strokes: vec![],
|
strokes: Vec::with_capacity(1),
|
||||||
blend_mode: BlendMode::default(),
|
blend_mode: BlendMode::default(),
|
||||||
opacity: 1.,
|
opacity: 1.,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
blur: Blur::default(),
|
blur: Blur::default(),
|
||||||
svg: None,
|
svg: None,
|
||||||
svg_attrs: HashMap::new(),
|
svg_attrs: HashMap::new(),
|
||||||
shadows: vec![],
|
shadows: Vec::with_capacity(1),
|
||||||
layout_item: None,
|
layout_item: None,
|
||||||
extrect: OnceCell::new(),
|
extrect: OnceCell::new(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
use std::collections::{hash_map::Entry, HashMap};
|
use std::collections::{hash_map::Entry, HashMap};
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use skia_safe as skia;
|
use skia_safe as skia;
|
||||||
|
|
||||||
|
use crate::performance;
|
||||||
use crate::render::RenderState;
|
use crate::render::RenderState;
|
||||||
use crate::shapes::Shape;
|
use crate::shapes::Shape;
|
||||||
use crate::shapes::StructureEntry;
|
use crate::shapes::StructureEntry;
|
||||||
use crate::tiles;
|
use crate::tiles;
|
||||||
use crate::uuid::Uuid;
|
use crate::uuid::Uuid;
|
||||||
|
|
||||||
|
const SHAPES_POOL_ALLOC_MULTIPLIER: f32 = 1.3;
|
||||||
|
|
||||||
/// A pool allocator for `Shape` objects that attempts to minimize memory reallocations.
|
/// A pool allocator for `Shape` objects that attempts to minimize memory reallocations.
|
||||||
///
|
///
|
||||||
/// `ShapesPool` pre-allocates a contiguous vector of boxed `Shape` instances,
|
/// `ShapesPool` pre-allocates a contiguous vector of boxed `Shape` instances,
|
||||||
|
@ -40,16 +44,29 @@ impl ShapesPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(&mut self, capacity: usize) {
|
pub fn initialize(&mut self, capacity: usize) {
|
||||||
|
performance::begin_measure!("shapes_pool_initialize");
|
||||||
self.counter = 0;
|
self.counter = 0;
|
||||||
self.shapes = Vec::with_capacity(capacity);
|
let additional = capacity as i32 - self.shapes.len() as i32;
|
||||||
for _ in 0..capacity {
|
if additional <= 0 {
|
||||||
self.shapes.push(Box::new(Shape::new(Uuid::nil())));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.shapes.extend(
|
||||||
|
iter::repeat_with(
|
||||||
|
|| Box::new(Shape::new(Uuid::nil()))
|
||||||
|
).take(additional as usize)
|
||||||
|
);
|
||||||
|
performance::end_measure!("shapes_pool_initialize");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_shape(&mut self, id: Uuid) -> &mut Shape {
|
pub fn add_shape(&mut self, id: Uuid) -> &mut Shape {
|
||||||
if self.counter >= self.shapes.len() {
|
if self.counter >= self.shapes.len() {
|
||||||
self.shapes.push(Box::new(Shape::new(Uuid::nil())));
|
let additional = (self.shapes.len() as f32 * SHAPES_POOL_ALLOC_MULTIPLIER) as usize;
|
||||||
|
self.shapes.extend(
|
||||||
|
iter::repeat_with(
|
||||||
|
|| Box::new(Shape::new(Uuid::nil()))
|
||||||
|
).take(additional)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let new_shape = &mut self.shapes[self.counter];
|
let new_shape = &mut self.shapes[self.counter];
|
||||||
new_shape.id = id;
|
new_shape.id = id;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue