perf(scene): parallelize block-definition build

Phase 2.1. build_defn stores nested INSERTs as by-name references and
never expands them at build time, so each block defn depends only on the
read-only doc — the builds are independent, not topologically ordered as
the roadmap assumed. Replace the serial loop with a rayon
par_iter().collect(). render_style_for / tessellate already run under
rayon in build_derived_caches, so thread-safety is established.

compute_block_aabbs stays serial (resolves nested refs, cheap post-pass).
Cuts first-frame block tessellation on insert-heavy drawings.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-05 00:46:21 +03:00
1 parent 997538a67a
commit 16050909f9
2 files changed
+18 -9

No files matched your search

+11 -4
View File
@@ -125,12 +125,19 @@ impl BlockCache {
/// because their entities are emitted as top-level wires, not via the
/// cache.
pub fn build(doc: &CadDocument, anno_scale: f32, bg_color: [f32; 4]) -> Self {
use rayon::prelude::*;
let mut cache = Self::new();
let referenced = collect_referenced_blocks(doc);
for name in &referenced {
let defn = build_defn(doc, name, anno_scale, bg_color);
cache.defns.insert(name.clone(), Arc::new(defn));
}
// Each defn is built independently: nested INSERTs are stored as
// by-name references (`LocalSub::Nested`), never expanded here, so a
// block's build never depends on another block's defn. That makes the
// builds embarrassingly parallel over the read-only `doc` — no
// topological ordering required. `compute_block_aabbs` stays a serial
// post-pass (it resolves nested references and is comparatively cheap).
cache.defns = referenced
.par_iter()
.map(|name| (name.clone(), Arc::new(build_defn(doc, name, anno_scale, bg_color))))
.collect();
cache.compute_block_aabbs(&referenced);
cache
}