forked from 1b-agent/opencadstudio-upstream
perf(scene): parallelize block AABB post-pass
Extends Phase 2.1. compute_block_aabbs resolved each defn's union AABB serially via defn_aabb_recursive, which only reads the finished defns map and re-walks shared nested defns with no memoization — real cost on block-heavy drawings. Split into a parallel read phase (per-name resolves fan out over rayon) and a serial write-back phase. BlockCache is Sync, so sharing &self across the read phase is sound. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
9b112ce12c
commit
44eea23c3f
2 files changed
+20
-6
No files matched your search
+4
-1
@@ -114,7 +114,10 @@ No topological stratification was needed after all: `build_defn` stores
|
||||
nested INSERTs as by-name references (`LocalSub::Nested`) and never expands
|
||||
them at build time, so each defn depends only on the read-only `doc` — the
|
||||
builds are embarrassingly parallel. Now a plain rayon `par_iter().collect()`.
|
||||
`compute_block_aabbs` stays a serial post-pass (resolves nested refs, cheap).
|
||||
`compute_block_aabbs` is also parallelized: its `defn_aabb_recursive` walk is
|
||||
read-only over the finished `defns` map and re-walks shared nested defns
|
||||
(no memo), so the per-name resolves fan out across rayon (read phase), then a
|
||||
serial phase stores each AABB back.
|
||||
|
||||
### 2.2 Incremental wire cache (delta tessellation)
|
||||
|
||||
|
||||
@@ -151,11 +151,22 @@ impl BlockCache {
|
||||
/// called in. Cycle guard: a self-referential block keeps an empty AABB
|
||||
/// (will fail every frustum test → not emitted, which is correct).
|
||||
fn compute_block_aabbs(&mut self, names: &[String]) {
|
||||
// Snapshot defn pointers up front — we mutate the map below.
|
||||
let names: Vec<String> = names.to_vec();
|
||||
for name in &names {
|
||||
let mut visited: Vec<String> = Vec::new();
|
||||
let aabb = self.defn_aabb_recursive(name, &mut visited);
|
||||
use rayon::prelude::*;
|
||||
// Phase 1 (parallel, read-only): each defn's union AABB is resolved
|
||||
// by `defn_aabb_recursive`, which only *reads* `self.defns` (the map
|
||||
// is fully built by now). There's no memoization, so a defn shared by
|
||||
// many parents is re-walked per parent — real work on block-heavy
|
||||
// drawings — and the per-name walks are independent, so they fan out.
|
||||
let this: &Self = self;
|
||||
let resolved: Vec<(&String, [f32; 4])> = names
|
||||
.par_iter()
|
||||
.map(|name| {
|
||||
let mut visited: Vec<String> = Vec::new();
|
||||
(name, this.defn_aabb_recursive(name, &mut visited))
|
||||
})
|
||||
.collect();
|
||||
// Phase 2 (serial): store the AABB back into each defn.
|
||||
for (name, aabb) in resolved {
|
||||
if let Some(defn_arc) = self.defns.get_mut(name) {
|
||||
let mut defn = (**defn_arc).clone();
|
||||
defn.aabb_local = aabb;
|
||||
|
||||
Reference in new issue
Block a user