perf(scene): return the memoized wire set by Arc, not by deep copy

entity_wires() cloned the entire wire set — every point, fill, and snap
buffer of every entity — on each call, although the set is already
memoized behind an Arc and none of the 18 call sites mutates it. On
large mesh imports (#358: 42M faces, ~210 MB of wire content per 1M
triangles) that is a multi-GB allocation + memcpy on every pick, snap,
selection, or plot pass.

Return the Arc instead. Call sites iterate as before; the two
window-plot paths that build a culled owned subset now clone only the
wires inside the plot window, and the print pipeline moves the Arc into
its async task.

Measured (tests/mem_probe_meshent.rs, 1M-triangle MESH, release):
resident after entity_wires() drops 758 -> 547 MB (866 -> 646 B/face).

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Kevin GriffinandClaude Fable 5 committed 2026-07-22 12:56:36 -07:00
1 parent 805da6428a
commit f347a20a4c
3 files changed
+19 -13

No files matched your search

+9 -5
View File
@@ -2851,9 +2851,9 @@ impl Scene {
/// Collect closed polygon outlines (world XY) from the current layout.
pub fn closed_outlines(&self) -> Vec<Vec<[f32; 2]>> {
self.entity_wires()
.into_iter()
.iter()
.filter_map(|wire| {
let pts = wire.points;
let pts = &wire.points;
if pts.len() < 4 {
return None;
}
@@ -2872,7 +2872,7 @@ impl Scene {
// boundary commands) see one vertex per corner — not the doubled
// ring that otherwise shows two grips at every corner.
let mut ring: Vec<[f32; 2]> = Vec::with_capacity(pts.len());
for p in &pts {
for p in pts {
if !p[0].is_finite() || !p[1].is_finite() {
continue;
}
@@ -3342,8 +3342,12 @@ impl Scene {
}
/// Build WireModels from all document entities + optional preview wire.
pub fn entity_wires(&self) -> Vec<WireModel> {
(*self.entity_wires_arc()).clone()
///
/// Returns the memoized set by `Arc` — callers only ever iterate it, and
/// the previous per-call deep clone was a full copy of every wire buffer
/// (hundreds of MB on large mesh imports, #358).
pub fn entity_wires(&self) -> Arc<Vec<WireModel>> {
self.entity_wires_arc()
}
/// Per-entity normalized draw-order depth, keyed by entity handle value.