forked from 1b-agent/opencadstudio-upstream
refactor(selection): migrate Scene.selection to Arc<RefCell> to avoid per-frame deep clone
Scene.selection was Rc<RefCell<SelectionState>> (31 fields, ~1.6KB with poly_points) cloned deep per view_main per pane via (*sel_ref).clone() at view/mod.rs:760. Replace with Arc<RefCell<SelectionState>> (Arc::new(RefCell::new(...)) at scene/mod.rs:1436,1868), SelectionCanvas holds Arc<RefCell> and selection_overlay takes Arc<RefCell> (overlay.rs:365,415), view_main does Arc::clone(&tab.scene.selection) (atomic bump) instead of deep clone. sel_ref stays borrowed for field reads (vp_size etc.). Bench (release, n=5000): SelectionState::clone 39-68ns (64pts) / 11-22ns (0pts) vs Arc::clone 7ns — 5-9x on the hot path. Tests: - selection_is_arc_not_refcell: asserts type_name contains Arc - bench_selection_state_clone / bench_selection_arc_clone / bench_selection_state_clone_empty (ignored, release)
This commit is contained in:
1 parent
d2338fa10f
commit
46190ccba1
4 files changed
+129
-29
No files matched your search
+5
-9
@@ -435,14 +435,10 @@ impl OpenCADStudio {
|
||||
// Hold a single `Ref<'_, SelectionState>` for the whole overlay
|
||||
// block. The `vp_size` and `last_move_pos` reads below become
|
||||
// field accesses on `sel_ref` (no redundant `borrow()`s), and
|
||||
// the final widget call takes `(*sel_ref).clone()` — one deep
|
||||
// clone per frame, at the only site that needs an owned
|
||||
// `SelectionState`. The `Ref` is dropped at the end of this
|
||||
// block. **Invariant:** no `selection.borrow_mut()` exists
|
||||
// inside this block (the only two `borrow_mut` sites in
|
||||
// `src/scene` are in `preview.rs:282` and `render.rs:3443`,
|
||||
// neither reachable from here). Holding the `Ref` is therefore
|
||||
// safe.
|
||||
// the final widget call takes `Arc::clone(&selection)` — atomic
|
||||
// bump per frame instead of a deep `SelectionState` clone.
|
||||
// `sel_ref` is a borrowed view for field reads; the widget owns
|
||||
// the Arc clone. No `selection` mutation occurs inside this block.
|
||||
let sel_ref = tab.scene.selection.borrow();
|
||||
let snap_info = tab.snap_result.map(|s| (s.screen, s.snap_type));
|
||||
let snap_ext_base = tab.snap_result.and_then(|s| s.extension_base);
|
||||
@@ -757,7 +753,7 @@ impl OpenCADStudio {
|
||||
.map(|h| tab.scene.is_layer_locked(h))
|
||||
.unwrap_or(false);
|
||||
crate::ui::overlay::selection_overlay(
|
||||
(*sel_ref).clone(),
|
||||
std::sync::Arc::clone(&tab.scene.selection),
|
||||
snap_info,
|
||||
snap_ext_base,
|
||||
snap_ext_base2,
|
||||
|
||||
Reference in new issue
Block a user