forked from 1b-agent/opencadstudio-upstream
perf: separate the two costs inside the visible-entity selection
The first drawn point costs 1068 ms and `wires-build` owns 710 of it:
visible=402.5 build=148.4 [classify=18.4 hits=127.5] sort=41.9
memo_hit=186455 memo_miss=1 candidates=444938
The memo is doing its job. `visible` is not, and two things in that loop
could own the 402 ms: resolving each handle through the document's hash
index, or the predicate — which reaches `document.layers.get(&c.layer)`,
a **string-keyed** lookup, so a string hash per entity, 444 938 times.
They call for different fixes, so `visible_probe=` times a resolve-only
pass and the remainder is the predicate. The pass repeats the resolve
rather than reading the clock inside the loop, where the measurement would
cost more than the thing measured, and it runs under PERF only.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
6b03e4cf17
commit
d5859a01a5
1 file changed
+22
-1
+22
-1
@@ -8939,6 +8939,11 @@ impl Scene {
|
||||
// version of this diagnostic report a constant.
|
||||
let visible_path: &str;
|
||||
let mut visible_candidates: usize;
|
||||
// `visible` costs ~400 ms over 444 937 candidates, and two things in
|
||||
// the loop could own that: resolving each handle through the document's
|
||||
// hash index, or the predicate, which looks a layer up **by name** —
|
||||
// a string hash per entity. Timed separately, under PERF only.
|
||||
let mut visible_probe_ms = 0.0f64;
|
||||
|
||||
// Phase 2.1 — quadtree-driven candidate selection. When a view
|
||||
// AABB exists (Model layout with a settled camera), only iterate
|
||||
@@ -9027,6 +9032,20 @@ impl Scene {
|
||||
}
|
||||
}
|
||||
}
|
||||
if perf {
|
||||
// A second, resolve-only pass. It repeats work rather than
|
||||
// instrumenting inside the loop, where a clock read per
|
||||
// iteration would cost more than what it measures.
|
||||
let t_probe = iced::time::Instant::now();
|
||||
let mut resolved = 0usize;
|
||||
for &handle in claimed {
|
||||
if self.document.get_entity(handle).is_some() {
|
||||
resolved += 1;
|
||||
}
|
||||
}
|
||||
std::hint::black_box(resolved);
|
||||
visible_probe_ms = t_probe.elapsed().as_secs_f64() * 1000.0;
|
||||
}
|
||||
out
|
||||
};
|
||||
|
||||
@@ -9271,7 +9290,8 @@ impl Scene {
|
||||
"[perf] wires-build total={:.1}ms sort_cache={:.1} visible={:.1} blk_cache={:.1} colors={:.1} \
|
||||
build={:.1} [classify={:.1} hits={:.1} tess={:.1} materialize={:.1}] sort={:.1}({}) \
|
||||
entities={} memo_hit={} memo_miss={} wires={} memo={} visible_path={} candidates={} \
|
||||
guard={:016x} guard_stale={} avp={} anno={:.4} anno_h={} all_vis={} sdf_gen={}",
|
||||
guard={:016x} guard_stale={} avp={} anno={:.4} anno_h={} all_vis={} sdf_gen={} \
|
||||
visible_probe={:.1}",
|
||||
crate::perf::elapsed_ms(t_fn),
|
||||
sort_cache_ms,
|
||||
visible_ms,
|
||||
@@ -9298,6 +9318,7 @@ guard={:016x} guard_stale={} avp={} anno={:.4} anno_h={} all_vis={} sdf_gen={}",
|
||||
annotation_scale_handle.map(|h| h.value()).unwrap_or(0),
|
||||
all_visible,
|
||||
crate::scene::text::sdf_atlas::generation(),
|
||||
visible_probe_ms,
|
||||
);
|
||||
}
|
||||
wires
|
||||
|
||||
Reference in new issue
Block a user