forked from 1b-agent/opencadstudio-upstream
perf(render): arena on by default; trim per-edit resident + text work
Three cuts to the per-edit cost, on top of the incremental wire arena: - Enable OCS_WIRE_GPU_PATCH by default (kill-switch OCS_WIRE_GPU_PATCH=0), so the in-place / append-tombstone arena — validated on the reference drawing (wire block ~300ms + 265MB upload -> ~2ms) — is on for everyone; a bail always falls back to the identical batched path. - Resident patch: an all-Modified edit never reorders, so reassemble by walking the recorded assembled order (~10k handles) instead of scanning the whole document (~800k) to re-derive draw order. Add/Remove still scan (positions change). ~14ms -> <1ms on a move. - SDF text: a new content id misses the glyph cache every edit, but if no text-bearing entity (Text/MText/Dimension/MLeader/Leader/Table/attribute/INSERT) changed since the last build the glyphs are identical, so reuse them. ~23ms -> 0 on a plain-geometry edit. A move/edit on this 800k-entity drawing now spends ~50ms (dominated by the undo document clone) instead of ~85ms, and the wire GPU upload is gone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
f12100d783
commit
aea1fd2caa
2 files changed
+104
-19
No files matched your search
@@ -990,6 +990,25 @@ impl Scene {
|
||||
return verts.clone();
|
||||
}
|
||||
}
|
||||
// A new content id (every geometry edit) misses the cache — but if no
|
||||
// text-bearing entity changed since the last build, the glyphs are
|
||||
// identical, so reuse them instead of re-walking every wire.
|
||||
{
|
||||
let reuse = {
|
||||
let last = self.last_sdf_text.borrow();
|
||||
match &*last {
|
||||
Some((epoch, arc)) if self.text_unchanged(*epoch) => Some(arc.clone()),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
if let Some(arc) = reuse {
|
||||
self.sdf_text_cache
|
||||
.borrow_mut()
|
||||
.insert(wire_content_id, arc.clone());
|
||||
*self.last_sdf_text.borrow_mut() = Some((self.geometry_epoch, arc.clone()));
|
||||
return arc;
|
||||
}
|
||||
}
|
||||
let mut out: Vec<crate::scene::pipeline::text_gpu::TextVertex> = Vec::new();
|
||||
for w in wires {
|
||||
if !w.text_verts.is_empty() {
|
||||
@@ -997,12 +1016,15 @@ impl Scene {
|
||||
}
|
||||
}
|
||||
let verts = Arc::new(out);
|
||||
let mut cache = self.sdf_text_cache.borrow_mut();
|
||||
// Ids change on rebuild, so old keys die naturally; cap bounds churn.
|
||||
if cache.len() > 8 {
|
||||
cache.clear();
|
||||
{
|
||||
let mut cache = self.sdf_text_cache.borrow_mut();
|
||||
// Ids change on rebuild, so old keys die naturally; cap bounds churn.
|
||||
if cache.len() > 8 {
|
||||
cache.clear();
|
||||
}
|
||||
cache.insert(wire_content_id, verts.clone());
|
||||
}
|
||||
cache.insert(wire_content_id, verts.clone());
|
||||
*self.last_sdf_text.borrow_mut() = Some((self.geometry_epoch, verts.clone()));
|
||||
verts
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user