From 354bf93364453e696a34b3b9a9c29bcb066578a0 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 23 Aug 2025 17:24:41 +0200 Subject: [PATCH] Store document node inputs in Arc to reduce memory consumption (#3086) Store values in memo hash contanier in arc --- .../document/utility_types/network_interface.rs | 3 ++- node-graph/gcore/src/memo.rs | 14 +++++++------- node-graph/graph-craft/src/document/value.rs | 3 ++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface.rs b/editor/src/messages/portfolio/document/utility_types/network_interface.rs index 575335bb..21e3860b 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface.rs @@ -25,6 +25,7 @@ use kurbo::BezPath; use serde_json::{Value, json}; use std::collections::{HashMap, HashSet, VecDeque}; use std::hash::{DefaultHasher, Hash, Hasher}; +use std::ops::Deref; /// All network modifications should be done through this API, so the fields cannot be public. However, all fields within this struct can be public since it it not possible to have a public mutable reference. #[derive(Debug, Default, serde::Serialize, serde::Deserialize)] @@ -1281,7 +1282,7 @@ impl NodeNetworkInterface { let artboard = self.document_node(&artboard_node_identifier.to_node(), &[]); let clip_input = artboard.unwrap().inputs.get(5).unwrap(); if let NodeInput::Value { tagged_value, .. } = clip_input { - if tagged_value.clone().into_inner() == TaggedValue::Bool(true) { + if tagged_value.clone().deref() == &TaggedValue::Bool(true) { return Some(Quad::clip( self.document_metadata.bounding_box_document(layer).unwrap_or_default(), self.document_metadata.bounding_box_document(artboard_node_identifier).unwrap_or_default(), diff --git a/node-graph/gcore/src/memo.rs b/node-graph/gcore/src/memo.rs index 81f4a735..012992e0 100644 --- a/node-graph/gcore/src/memo.rs +++ b/node-graph/gcore/src/memo.rs @@ -156,10 +156,10 @@ pub mod monitor { pub const IDENTIFIER: crate::ProtoNodeIdentifier = crate::ProtoNodeIdentifier::new("graphene_core::memo::MonitorNode"); } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct MemoHash { hash: u64, - value: T, + value: Arc, } impl<'de, T: serde::Deserialize<'de> + Hash> serde::Deserialize<'de> for MemoHash { @@ -183,10 +183,10 @@ impl serde::Serialize for MemoHash { impl MemoHash { pub fn new(value: T) -> Self { let hash = Self::calc_hash(&value); - Self { hash, value } + Self { hash, value: value.into() } } pub fn new_with_hash(value: T, hash: u64) -> Self { - Self { hash, value } + Self { hash, value: value.into() } } fn calc_hash(data: &T) -> u64 { @@ -198,7 +198,7 @@ impl MemoHash { pub fn inner_mut(&mut self) -> MemoHashGuard<'_, T> { MemoHashGuard { inner: self } } - pub fn into_inner(self) -> T { + pub fn into_inner(self) -> Arc { self.value } pub fn hash_code(&self) -> u64 { @@ -244,8 +244,8 @@ impl Deref for MemoHashGuard<'_, T> { } } -impl std::ops::DerefMut for MemoHashGuard<'_, T> { +impl std::ops::DerefMut for MemoHashGuard<'_, T> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner.value + Arc::make_mut(&mut self.inner.value) } } diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index 56f3c963..e5d3844a 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -392,7 +392,8 @@ impl<'input> Node<'input, DAny<'input>> for UpcastNode { type Output = FutureAny<'input>; fn eval(&'input self, _: DAny<'input>) -> Self::Output { - Box::pin(async move { self.value.clone().into_inner().to_dynany() }) + let memo_clone = MemoHash::clone(&self.value); + Box::pin(async move { memo_clone.into_inner().as_ref().clone().to_dynany() }) } } impl UpcastNode {