Box the largest message and update payloads

This commit is contained in:
Dennis Kobert
2026-09-09 15:39:37 +00:00
parent f566e8ee17
commit e10d56c261
12 changed files with 46 additions and 36 deletions
@@ -157,7 +157,8 @@ pub enum NodeGraphMessage {
SetInputValue { SetInputValue {
node_id: NodeId, node_id: NodeId,
input_index: usize, input_index: usize,
value: TaggedValue, // Boxed to keep the whole editor message tree small; `TaggedValue` alone is 568 bytes
value: Box<TaggedValue>,
}, },
SetInput { SetInput {
input_connector: InputConnector, input_connector: InputConnector,
@@ -1765,6 +1765,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
NodeGraphMessage::SetInputValue { node_id, input_index, value } => { NodeGraphMessage::SetInputValue { node_id, input_index, value } => {
use graphene_std::vector::generator_nodes::*; use graphene_std::vector::generator_nodes::*;
let value = *value;
let reference = network_interface.reference(&node_id, selection_network_path); let reference = network_interface.reference(&node_id, selection_network_path);
let is_text_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::text::text::IDENTIFIER)); let is_text_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::text::text::IDENTIFIER));
let is_stroke_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::vector::stroke::IDENTIFIER)); let is_stroke_node = reference.as_ref().is_some_and(|r| *r == DefinitionIdentifier::ProtoNode(graphene_std::vector::stroke::IDENTIFIER));
@@ -44,7 +44,12 @@ pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
fn optionally_update_value<T>(value: impl Fn(&T) -> Option<TaggedValue> + 'static + Send + Sync, node_id: NodeId, input_index: usize) -> impl Fn(&T) -> Message + 'static + Send + Sync { fn optionally_update_value<T>(value: impl Fn(&T) -> Option<TaggedValue> + 'static + Send + Sync, node_id: NodeId, input_index: usize) -> impl Fn(&T) -> Message + 'static + Send + Sync {
move |input_value: &T| match value(input_value) { move |input_value: &T| match value(input_value) {
Some(value) => NodeGraphMessage::SetInputValue { node_id, input_index, value }.into(), Some(value) => NodeGraphMessage::SetInputValue {
node_id,
input_index,
value: Box::new(value),
}
.into(),
None => Message::NoOp, None => Message::NoOp,
} }
} }
@@ -867,7 +872,7 @@ pub fn font_inputs(parameter_widgets_info: ParameterWidgetsInfo) -> (Vec<WidgetI
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: graphene_std::text::text::FontInput::INDEX, input_index: graphene_std::text::text::FontInput::INDEX,
value: TaggedValue::Resource(resource_id), value: Box::new(TaggedValue::Resource(resource_id)),
} }
.into(), .into(),
]), ]),
@@ -1437,7 +1442,7 @@ fn build_shared_spectrum_section(node_id: NodeId, context: &mut NodePropertiesCo
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index, input_index,
value: TaggedValue::F32(percent.clamp(0., 100.) as f32), value: Box::new(TaggedValue::F32(percent.clamp(0., 100.) as f32)),
} }
.into() .into()
} }
@@ -1594,7 +1599,7 @@ fn spectrum_slider_row(
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index, input_index,
value: TaggedValue::F32(position_to_value(new_position).clamp(value_min, value_max) as f32), value: Box::new(TaggedValue::F32(position_to_value(new_position).clamp(value_min, value_max) as f32)),
} }
.into() .into()
}) })
@@ -2148,13 +2153,13 @@ pub(crate) fn string_capitalization_properties(node_id: NodeId, context: &mut No
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: UseJoinerInput::INDEX, input_index: UseJoinerInput::INDEX,
value: TaggedValue::Bool(true), value: Box::new(TaggedValue::Bool(true)),
} }
.into(), .into(),
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: JoinerInput::INDEX, input_index: JoinerInput::INDEX,
value: TaggedValue::String(value.clone()), value: Box::new(TaggedValue::String(value.clone())),
} }
.into(), .into(),
]), ]),
@@ -2214,13 +2219,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: IndividualCornerRadiiInput::INDEX, input_index: IndividualCornerRadiiInput::INDEX,
value: TaggedValue::Bool(false), value: Box::new(TaggedValue::Bool(false)),
} }
.into(), .into(),
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: CornerRadiusInput::INDEX, input_index: CornerRadiusInput::INDEX,
value: TaggedValue::F64(uniform_val), value: Box::new(TaggedValue::F64(uniform_val)),
} }
.into(), .into(),
]), ]),
@@ -2234,13 +2239,13 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: IndividualCornerRadiiInput::INDEX, input_index: IndividualCornerRadiiInput::INDEX,
value: TaggedValue::Bool(true), value: Box::new(TaggedValue::Bool(true)),
} }
.into(), .into(),
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: CornerRadiusInput::INDEX, input_index: CornerRadiusInput::INDEX,
value: TaggedValue::F64Array(individual_val_for_switch.clone()), value: Box::new(TaggedValue::F64Array(individual_val_for_switch.clone())),
} }
.into(), .into(),
]), ]),
@@ -2549,13 +2554,13 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: FillInput::INDEX, input_index: FillInput::INDEX,
value: TaggedValue::Color(color), value: Box::new(TaggedValue::Color(color)),
} }
.into(), .into(),
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: BackupColorInput::INDEX, input_index: BackupColorInput::INDEX,
value: TaggedValue::Color(color), value: Box::new(TaggedValue::Color(color)),
} }
.into(), .into(),
]), ]),
@@ -2566,13 +2571,13 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: FillInput::INDEX, input_index: FillInput::INDEX,
value: TaggedValue::Gradient(gradient.clone()), value: Box::new(TaggedValue::Gradient(gradient.clone())),
} }
.into(), .into(),
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: BackupGradientInput::INDEX, input_index: BackupGradientInput::INDEX,
value: TaggedValue::Gradient(gradient), value: Box::new(TaggedValue::Gradient(gradient)),
} }
.into(), .into(),
]), ]),
@@ -2729,12 +2729,12 @@ impl NodeNetworkInterface {
DocumentNodeClickTargets { DocumentNodeClickTargets {
node_click_target, node_click_target,
port_click_targets, port_click_targets,
node_type_metadata: NodeTypeClickTargets::Layer(LayerClickTargets { node_type_metadata: NodeTypeClickTargets::Layer(Box::new(LayerClickTargets {
visibility_click_target, visibility_click_target,
lock_click_target, lock_click_target,
grip_click_target, grip_click_target,
name_click_target, name_click_target,
}), })),
} }
}; };
@@ -6953,7 +6953,7 @@ pub struct LayerTransientMetadata {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum NodeTypeClickTargets { pub enum NodeTypeClickTargets {
Layer(LayerClickTargets), Layer(Box<LayerClickTargets>),
Node, // No transient click targets are stored exclusively for nodes Node, // No transient click targets are stored exclusively for nodes
} }
@@ -52,7 +52,7 @@ pub enum PortfolioMessage {
reopened: bool, reopened: bool,
#[serde(skip, default)] #[serde(skip, default)]
#[derivative(Debug = "ignore", PartialEq = "ignore", Clone(clone_with = "clone_to_none"))] #[derivative(Debug = "ignore", PartialEq = "ignore", Clone(clone_with = "clone_to_none"))]
gdd: Option<document_format::GddV1>, gdd: Option<Box<document_format::GddV1>>,
}, },
DestroyAllDocuments, DestroyAllDocuments,
EditorPreferences, EditorPreferences,
@@ -305,7 +305,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
// Document was closed before its working copy finished mounting. // Document was closed before its working copy finished mounting.
return; return;
}; };
document.set_storage(gdd); document.set_storage(gdd.map(|gdd| *gdd));
if !reopened { if !reopened {
document.commit_storage_snapshot(&resource_storage.resources_mut(), preferences.validate_storage_round_trip); document.commit_storage_snapshot(&resource_storage.resources_mut(), preferences.validate_storage_round_trip);
document.retire_storage_interaction(); document.retire_storage_interaction();
@@ -1914,7 +1914,7 @@ impl PortfolioMessageHandler {
Message::Portfolio(PortfolioMessage::DocumentStorageMounted { Message::Portfolio(PortfolioMessage::DocumentStorageMounted {
document_id, document_id,
reopened, reopened,
gdd: Some(gdd), gdd: Some(Box::new(gdd)),
}) })
}; };
future.into() future.into()
@@ -613,7 +613,7 @@ pub fn set_stroke_weight_for_selected_layers(weight: f64, document: &DocumentMes
for layer in layers { for layer in layers {
if let Some(node_id) = get_stroke_id(layer, &document.network_interface) { if let Some(node_id) = get_stroke_id(layer, &document.network_interface) {
let input_index = graphene_std::vector::stroke::WeightInput::INDEX; let input_index = graphene_std::vector::stroke::WeightInput::INDEX;
let value = TaggedValue::F64(weight); let value = Box::new(TaggedValue::F64(weight));
responses.add(NodeGraphMessage::SetInputValue { node_id, input_index, value }); responses.add(NodeGraphMessage::SetInputValue { node_id, input_index, value });
} else if weight > 0. { } else if weight > 0. {
let color = Some(Color::BLACK); let color = Some(Color::BLACK);
@@ -825,7 +825,7 @@ pub fn set_stroke_color_for_selected_layers(color: Option<Color>, weight: f64, d
for layer in layers { for layer in layers {
if let Some(node_id) = get_stroke_id(layer, &document.network_interface) { if let Some(node_id) = get_stroke_id(layer, &document.network_interface) {
let input_index = graphene_std::vector::stroke::PaintInput::INDEX; let input_index = graphene_std::vector::stroke::PaintInput::INDEX;
let value = TaggedValue::Color(color); let value = Box::new(TaggedValue::Color(color));
responses.add(NodeGraphMessage::SetInputValue { node_id, input_index, value }); responses.add(NodeGraphMessage::SetInputValue { node_id, input_index, value });
} else { } else {
let stroke = graphene_std::vector::style::Stroke::new(weight); let stroke = graphene_std::vector::style::Stroke::new(weight);
@@ -896,7 +896,7 @@ pub fn set_proto_node_input_for_selected_layers(
responses.add(NodeGraphMessage::SetInputValue { responses.add(NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index, input_index,
value: value.clone(), value: Box::new(value.clone()),
}); });
} }
} }
@@ -2146,7 +2146,7 @@ mod test_gradient {
.handle_message(NodeGraphMessage::SetInputValue { .handle_message(NodeGraphMessage::SetInputValue {
node_id: gradient_node_id, node_id: gradient_node_id,
input_index: 1, input_index: 1,
value: TaggedValue::Gradient(GradientStops::new([ value: Box::new(TaggedValue::Gradient(GradientStops::new([
GradientStop { GradientStop {
position: 0., position: 0.,
midpoint: 0.5, midpoint: 0.5,
@@ -2157,7 +2157,7 @@ mod test_gradient {
midpoint: 0.5, midpoint: 0.5,
color: Color::BLUE, color: Color::BLUE,
}, },
])), ]))),
}) })
.await; .await;
@@ -2183,7 +2183,7 @@ mod test_gradient {
.handle_message(NodeGraphMessage::SetInputValue { .handle_message(NodeGraphMessage::SetInputValue {
node_id: gradient_node_id, node_id: gradient_node_id,
input_index: 1, input_index: 1,
value: TaggedValue::Gradient(GradientStops::new([ value: Box::new(TaggedValue::Gradient(GradientStops::new([
GradientStop { GradientStop {
position: 0., position: 0.,
midpoint: 0.5, midpoint: 0.5,
@@ -2194,7 +2194,7 @@ mod test_gradient {
midpoint: 0.5, midpoint: 0.5,
color: Color::BLUE, color: Color::BLUE,
}, },
])), ]))),
}) })
.await; .await;
@@ -2826,7 +2826,7 @@ mod test_gradient {
.handle_message(NodeGraphMessage::SetInputValue { .handle_message(NodeGraphMessage::SetInputValue {
node_id: gradient_value_id, node_id: gradient_value_id,
input_index: 1, input_index: 1,
value: TaggedValue::Gradient(GradientStops::new([ value: Box::new(TaggedValue::Gradient(GradientStops::new([
GradientStop { GradientStop {
position: 0., position: 0.,
midpoint: 0.5, midpoint: 0.5,
@@ -2837,7 +2837,7 @@ mod test_gradient {
midpoint: 0.5, midpoint: 0.5,
color: Color::BLUE, color: Color::BLUE,
}, },
])), ]))),
}) })
.await; .await;
@@ -118,7 +118,7 @@ fn create_text_widgets(tool: &TextTool, font_catalog: &FontCatalog, document: &D
NodeGraphMessage::SetInputValue { NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: graphene_std::text::text::FontInput::INDEX, input_index: graphene_std::text::text::FontInput::INDEX,
value: TaggedValue::Resource(resource_id), value: Box::new(TaggedValue::Resource(resource_id)),
} }
.into(), .into(),
]), ]),
@@ -349,7 +349,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Text
responses.add(NodeGraphMessage::SetInputValue { responses.add(NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: graphene_std::text::text::SizeInput::INDEX, input_index: graphene_std::text::text::SizeInput::INDEX,
value: TaggedValue::F64(font_size), value: Box::new(TaggedValue::F64(font_size)),
}); });
} }
} }
@@ -364,7 +364,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Text
responses.add(NodeGraphMessage::SetInputValue { responses.add(NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: graphene_std::text::text::AlignInput::INDEX, input_index: graphene_std::text::text::AlignInput::INDEX,
value: TaggedValue::TextAlign(align), value: Box::new(TaggedValue::TextAlign(align)),
}); });
} }
} }
+2 -2
View File
@@ -47,7 +47,7 @@ pub struct CompilationResponse {
} }
pub enum NodeGraphUpdate { pub enum NodeGraphUpdate {
ExecutionResponse(ExecutionResponse), ExecutionResponse(Box<ExecutionResponse>),
CompilationResponse(CompilationResponse), CompilationResponse(CompilationResponse),
EyedropperPreview(Raster<CPU>), EyedropperPreview(Raster<CPU>),
NodeGraphUpdateMessage(NodeGraphUpdateMessage), NodeGraphUpdateMessage(NodeGraphUpdateMessage),
@@ -368,7 +368,7 @@ impl NodeGraphExecutor {
responses: existing_responses, responses: existing_responses,
vector_modify, vector_modify,
inspect_result, inspect_result,
} = execution_response; } = *execution_response;
while let Some(&(queued_execution_id, _)) = self.futures.front() { while let Some(&(queued_execution_id, _)) = self.futures.front() {
if queued_execution_id < execution_id { if queued_execution_id < execution_id {
+1 -1
View File
@@ -104,7 +104,7 @@ impl InternalNodeGraphUpdateSender {
} }
fn send_execution_response(&self, response: ExecutionResponse) { fn send_execution_response(&self, response: ExecutionResponse) {
self.0.send(NodeGraphUpdate::ExecutionResponse(response)).expect("Failed to send response") self.0.send(NodeGraphUpdate::ExecutionResponse(Box::new(response))).expect("Failed to send response")
} }
fn send_eyedropper_preview(&self, raster: Raster<CPU>) { fn send_eyedropper_preview(&self, raster: Raster<CPU>) {
+3
View File
@@ -258,6 +258,9 @@ pub struct ParsedField {
pub(crate) attribute_reads: Vec<AttributeRead>, pub(crate) attribute_reads: Vec<AttributeRead>,
} }
// Both variants are large parsed-syntax payloads (888/672 bytes), so boxing one still leaves the other large while forcing a
// deref on every pattern match across codegen; this is built once per node at compile time, never on a hot path
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ParsedFieldType { pub enum ParsedFieldType {
Regular(RegularParsedField), Regular(RegularParsedField),