From c616f50bd0c7250d0ee7e663176aa687825fe0fc Mon Sep 17 00:00:00 2001 From: bherbruck Date: Tue, 13 Oct 2026 19:49:19 -0400 Subject: [PATCH] Open large designs faster: move bodies into components without copying the model (#915) A body transfer works out the moved bodies first and puts them in place in the evaluator's own copy of the model, instead of copying every body of the model for each transfer. --- crates/doc/src/body_transfer.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/doc/src/body_transfer.rs b/crates/doc/src/body_transfer.rs index 07fa5071..d29c2a34 100644 --- a/crates/doc/src/body_transfer.rs +++ b/crates/doc/src/body_transfer.rs @@ -31,11 +31,14 @@ pub fn validate_body_transfer(doc: &Document, bodies: &[String], from: u64, to: Ok(()) } +/// Moves the bodies in `st`, which the evaluator discards when this fails (so it is changed in +/// place rather than copied: a copy of every body for each moved one was most of the cost). pub(crate) fn evaluate(doc: &Document, st: &mut ModelState, bodies: &[String], from: u64, to: u64, transform: Mat) -> Result<()> { validate_body_transfer(doc, bodies, from, to, &transform)?; - let mut next = st.clone(); + let mut moved = Vec::with_capacity(bodies.len()); for name in bodies { - let old = st.body(name).ok_or_else(|| DocError::Unknown(format!("transferred body `{name}`")))?; + let (slot, old) = + st.bodies.iter().enumerate().find(|(_, b)| b.name == *name).ok_or_else(|| DocError::Unknown(format!("transferred body `{name}`")))?; if doc.model_body_component(old) != from { return Err(DocError::Invalid(format!("body `{name}` no longer belongs to transfer source component {from}"))); } @@ -47,12 +50,14 @@ pub(crate) fn evaluate(doc: &Document, st: &mut ModelState, bodies: &[String], f body.source_transform = crate::mat_mul(&transform, &old.source_transform); body.imported = old.imported.clone(); body.names = crate::naming::NameCell::same(old); - let slot = next.bodies.iter_mut().find(|b| b.name == *name).ok_or_else(|| DocError::Unknown(format!("transferred body `{name}`")))?; - *slot = body; + moved.push((slot, body)); } - crate::body_transfer_sheet::remap_sheet_metadata(&mut next, bodies, &transform)?; - *st = next; - Ok(()) + for (slot, body) in moved { + if let Some(b) = st.bodies.get_mut(slot) { + *b = body; + } + } + crate::body_transfer_sheet::remap_sheet_metadata(st, bodies, &transform) } #[cfg(test)]