Open large designs faster: count the cache budget without cloning wires (#911)
Body::retained_bytes counts face and edge uses on the borrowed boundaries (the same numbers, checked by a test), and each model body keeps the footprint measured when a feature made or changed it, so the evaluation cache's budget no longer walks every body's topology after every feature.
This commit is contained in:
1 parent
eaab205302
commit
648f0ff768
3 files changed
+31
-2
No files matched your search
@@ -44,6 +44,9 @@ pub struct ModelBody {
|
||||
pub transferred: bool,
|
||||
/// The look it was imported with, carried through later features.
|
||||
pub imported: Option<Arc<crate::appearance::ImportedLook>>,
|
||||
/// [`Body::retained_bytes`] of `body`, measured when a feature made or changed it (0: not
|
||||
/// measured), so the evaluation cache's budget does not walk every body after every feature.
|
||||
bytes: usize,
|
||||
}
|
||||
|
||||
impl ModelBody {
|
||||
@@ -62,6 +65,7 @@ impl ModelBody {
|
||||
component: 0,
|
||||
transferred: false,
|
||||
imported: None,
|
||||
bytes: 0,
|
||||
}
|
||||
}
|
||||
pub fn definition_name(&self) -> &str {
|
||||
@@ -486,6 +490,7 @@ impl ModelState {
|
||||
Some(x) => {
|
||||
b.key = x.key;
|
||||
b.names = x.names.clone();
|
||||
b.bytes = if x.bytes > 0 { x.bytes } else { b.body.retained_bytes() };
|
||||
}
|
||||
None => {
|
||||
let mut h = std::collections::hash_map::DefaultHasher::new();
|
||||
@@ -507,6 +512,7 @@ impl ModelState {
|
||||
{
|
||||
b.imported = crate::appearance::ImportedLook::of(old);
|
||||
}
|
||||
b.bytes = b.body.retained_bytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,7 +603,7 @@ impl ModelState {
|
||||
/// topology is what makes a kept timeline snapshot expensive, so it dominates; sketches
|
||||
/// and the rest are counted from their entity counts.
|
||||
pub fn retained_bytes(&self) -> usize {
|
||||
let bodies: usize = self.bodies.iter().map(|b| b.body.retained_bytes()).sum();
|
||||
let bodies: usize = self.bodies.iter().map(|b| if b.bytes > 0 { b.bytes } else { b.body.retained_bytes() }).sum();
|
||||
let sketches: usize = self.sketches.iter().map(|s| s.retained_bytes()).sum();
|
||||
bodies + sketches + self.sheets.len() * 4096 + self.threads.len() * 192 + self.construct.len() * 192
|
||||
}
|
||||
|
||||
@@ -939,7 +939,16 @@ impl Body {
|
||||
if let Some(m) = &self.mesh {
|
||||
return m.positions.len() * 24 + m.triangles.len() * 12;
|
||||
}
|
||||
self.solid.face_iter().count() * 2048 + self.solid.edge_iter().count() * 512 + self.solid.vertex_iter().count() * 96
|
||||
// Counted on the borrowed boundaries: `Solid::edge_iter` and `vertex_iter` clone every
|
||||
// face's wires to walk them, which made this estimate (taken after every feature, over
|
||||
// every body) cost more than evaluating most features. Each edge use is one edge and
|
||||
// one vertex in those iterators, so the counts are the same.
|
||||
let (mut faces, mut uses) = (0usize, 0usize);
|
||||
for face in self.solid.face_iter() {
|
||||
faces += 1;
|
||||
uses += face.absolute_boundaries().iter().map(|w| w.len()).sum::<usize>();
|
||||
}
|
||||
faces * 2048 + uses * (512 + 96)
|
||||
}
|
||||
|
||||
/// Distinct edges in a stable order (the order of `edges()` and `tessellate().edges`).
|
||||
|
||||
@@ -2312,3 +2312,17 @@ fn shell_of_a_disc_rounded_smaller_than_the_wall() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The cache-budget estimate counts edge and vertex uses on the borrowed boundaries; it must
|
||||
/// equal what walking the cloned wires (`Solid::edge_iter`, `vertex_iter`) counts.
|
||||
#[test]
|
||||
fn retained_bytes_matches_the_iterator_counts() {
|
||||
let block = box_solid(Vec3::ZERO, Vec3::new(40.0, 30.0, 10.0)).unwrap();
|
||||
let hole = cylinder(Vec3::new(20.0, 15.0, -5.0), Vec3::Z, 5.0, 30.0).unwrap();
|
||||
let drilled = boolean(&block, &hole, BoolOp::Cut).unwrap().unwrap();
|
||||
for body in [&block, &hole, &drilled] {
|
||||
let s = &body.solid;
|
||||
let walked = s.face_iter().count() * 2048 + s.edge_iter().count() * 512 + s.vertex_iter().count() * 96;
|
||||
assert_eq!(body.retained_bytes(), walked);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user