forked from 1b-agent/opencadstudio-upstream
bench(flatten): add FLATTEN metrics with extracted helpers
Moves the flatten projection fns and command helpers into modules/draw/modify/flatten.rs (behavior unchanged) and adds flatten_plan / flatten_scene_apply to the COMMANDS suite.
This commit is contained in:
1 parent
51d26eb81f
commit
91900c4e73
5 files changed
+660
-452
No files matched your search
@@ -8,7 +8,8 @@ use std::hint::black_box;
|
||||
use std::time::Instant;
|
||||
|
||||
use codec::entities::{
|
||||
Dimension, DimensionLinear, Insert, Line, LwPolyline, LwVertex, MLine,
|
||||
Circle, Dimension, DimensionLinear, Insert, Line, LwPolyline, LwVertex, MLine, Point,
|
||||
Polyline2D, Polyline3D, Ray, Solid, Text, Vertex2D, Vertex3DPolyline,
|
||||
};
|
||||
use codec::tables::BlockRecord;
|
||||
use codec::types::{Vector2, Vector3};
|
||||
@@ -18,6 +19,7 @@ use harness::BenchmarkRunner;
|
||||
use OpenCADStudio::modules::draw::modify::explode::{
|
||||
apply_explode_replacements, explode_batch,
|
||||
};
|
||||
use OpenCADStudio::modules::draw::modify::flatten;
|
||||
use OpenCADStudio::scene::Scene;
|
||||
|
||||
const BLOCK_NAME: &str = "BENCH_BLOCK";
|
||||
@@ -238,6 +240,173 @@ fn bench_explode_scene_apply(runner: &mut BenchmarkRunner) {
|
||||
);
|
||||
}
|
||||
|
||||
/// (lines, circles, polyline3d, polyline2d, texts, points, solids, rays, flat
|
||||
/// lines) — full = 2,500 entities, 2,300 of which move.
|
||||
fn flatten_counts(quick: bool) -> [usize; 9] {
|
||||
if quick {
|
||||
[120, 60, 80, 60, 60, 40, 40, 20, 20] // 500 total, 460 move
|
||||
} else {
|
||||
[600, 300, 400, 300, 300, 200, 200, 100, 100] // 2,500 total, 2,300 move
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_fixture_entities(quick: bool) -> usize {
|
||||
flatten_counts(quick).iter().sum()
|
||||
}
|
||||
|
||||
fn flatten_moved_expected(quick: bool) -> usize {
|
||||
flatten_fixture_entities(quick) - if quick { 40 } else { 200 }
|
||||
}
|
||||
|
||||
/// Mixed-Z fixture: everything non-flat except the trailing ray + flat-line
|
||||
/// groups, which FLATTEN must leave untouched (None).
|
||||
fn push_flatten_fixture(doc: &mut CadDocument, quick: bool) -> Vec<Handle> {
|
||||
let [n_line, n_circle, n_pl3d, n_pl2d, n_text, n_point, n_solid, n_ray, n_flat] =
|
||||
flatten_counts(quick);
|
||||
let mut handles = Vec::with_capacity(flatten_fixture_entities(quick));
|
||||
|
||||
for i in 0..n_line {
|
||||
let mut line = Line::new();
|
||||
let x = i as f64;
|
||||
line.start = Vector3::new(x, 0.0, 1.0 + (i % 5) as f64);
|
||||
line.end = Vector3::new(x + 1.0, 1.0, 2.0);
|
||||
line.thickness = 1.0;
|
||||
handles.push(doc.add_entity(EntityType::Line(line)).unwrap());
|
||||
}
|
||||
for i in 0..n_circle {
|
||||
let mut c = Circle::from_center_radius(Vector3::new(i as f64, 0.0, 1.0 + (i % 3) as f64), 2.0);
|
||||
if i % 2 == 1 {
|
||||
c.normal = Vector3::new(0.0, 0.6, 0.8); // tilted → ellipse
|
||||
}
|
||||
handles.push(doc.add_entity(EntityType::Circle(c)).unwrap());
|
||||
}
|
||||
for i in 0..n_pl3d {
|
||||
let mut pl = Polyline3D::new();
|
||||
pl.elevation = (i % 4) as f64;
|
||||
for k in 0..6 {
|
||||
pl.vertices.push(Vertex3DPolyline::new(Vector3::new(
|
||||
i as f64 + k as f64,
|
||||
k as f64,
|
||||
1.0 + (k % 3) as f64,
|
||||
)));
|
||||
}
|
||||
handles.push(doc.add_entity(EntityType::Polyline3D(pl)).unwrap());
|
||||
}
|
||||
for i in 0..n_pl2d {
|
||||
let mut pl = Polyline2D::new();
|
||||
pl.elevation = 3.0 + (i % 5) as f64;
|
||||
for k in 0..6 {
|
||||
pl.vertices.push(Vertex2D::new(Vector3::new(k as f64, i as f64, 0.0)));
|
||||
}
|
||||
handles.push(doc.add_entity(EntityType::Polyline2D(pl)).unwrap());
|
||||
}
|
||||
for i in 0..n_text {
|
||||
let mut t = Text::new();
|
||||
t.insertion_point = Vector3::new(i as f64, 0.0, 1.5);
|
||||
handles.push(doc.add_entity(EntityType::Text(t)).unwrap());
|
||||
}
|
||||
for i in 0..n_point {
|
||||
let mut p = Point::new();
|
||||
p.location = Vector3::new(i as f64, 1.0, 0.75);
|
||||
handles.push(doc.add_entity(EntityType::Point(p)).unwrap());
|
||||
}
|
||||
for i in 0..n_solid {
|
||||
let x = i as f64;
|
||||
let s = Solid::new(
|
||||
Vector3::new(x, 0.0, 1.0),
|
||||
Vector3::new(x + 1.0, 0.0, 2.0),
|
||||
Vector3::new(x + 1.0, 1.0, 3.0),
|
||||
Vector3::new(x, 1.0, 4.0),
|
||||
);
|
||||
handles.push(doc.add_entity(EntityType::Solid(s)).unwrap());
|
||||
}
|
||||
for i in 0..n_ray {
|
||||
let r = Ray::new(Vector3::new(i as f64, 0.0, 5.0), Vector3::new(0.0, 0.0, 1.0));
|
||||
handles.push(doc.add_entity(EntityType::Ray(r)).unwrap());
|
||||
}
|
||||
for i in 0..n_flat {
|
||||
let mut line = Line::new();
|
||||
let x = i as f64;
|
||||
line.start = Vector3::new(x, 0.0, 0.0);
|
||||
line.end = Vector3::new(x + 1.0, 1.0, 0.0);
|
||||
handles.push(doc.add_entity(EntityType::Line(line)).unwrap());
|
||||
}
|
||||
handles
|
||||
}
|
||||
|
||||
/// FLATTEN plan: collect candidates + compute replacements (fresh doc/sample).
|
||||
fn bench_flatten_plan(runner: &mut BenchmarkRunner) {
|
||||
let name = "flatten_plan";
|
||||
if !runner.should_run(name) {
|
||||
return;
|
||||
}
|
||||
let quick = runner.quick_mode;
|
||||
let sample_count = if quick { 3 } else { 10 };
|
||||
let entity_count = flatten_fixture_entities(quick);
|
||||
let moved_expected = flatten_moved_expected(quick);
|
||||
let mut times = Vec::with_capacity(sample_count);
|
||||
|
||||
for _ in 0..sample_count {
|
||||
let mut scene = Scene::new();
|
||||
push_flatten_fixture(&mut scene.document, quick);
|
||||
|
||||
let t0 = Instant::now();
|
||||
let candidates = black_box(flatten::collect_flatten_handles(&scene));
|
||||
let updates = black_box(flatten::plan_flatten(&scene, &candidates));
|
||||
times.push(t0.elapsed().as_micros() as f64);
|
||||
|
||||
assert_eq!(candidates.len(), entity_count);
|
||||
assert_eq!(updates.len(), moved_expected);
|
||||
}
|
||||
|
||||
let med = median(×);
|
||||
let throughput = entity_count as f64 / (med / 1_000_000.0);
|
||||
runner.record(
|
||||
name,
|
||||
"FLATTEN plan: collect_flatten_handles + plan_flatten over the mixed-Z fixture",
|
||||
"us",
|
||||
times,
|
||||
Some((throughput, "entities/s")),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
/// FLATTEN apply: fresh Scene per sample, plan computed untimed, the publish
|
||||
/// loop timed.
|
||||
fn bench_flatten_scene_apply(runner: &mut BenchmarkRunner) {
|
||||
let name = "flatten_scene_apply";
|
||||
if !runner.should_run(name) {
|
||||
return;
|
||||
}
|
||||
let quick = runner.quick_mode;
|
||||
let sample_count = if quick { 3 } else { 10 };
|
||||
let moved_expected = flatten_moved_expected(quick);
|
||||
let mut times = Vec::with_capacity(sample_count);
|
||||
|
||||
for _ in 0..sample_count {
|
||||
let mut scene = Scene::new();
|
||||
let handles = push_flatten_fixture(&mut scene.document, quick);
|
||||
let updates = flatten::plan_flatten(&scene, &handles);
|
||||
assert_eq!(updates.len(), moved_expected);
|
||||
|
||||
let t0 = Instant::now();
|
||||
let moved = black_box(flatten::apply_flatten_updates(&mut scene, updates));
|
||||
times.push(t0.elapsed().as_micros() as f64);
|
||||
assert_eq!(moved, moved_expected);
|
||||
}
|
||||
|
||||
let med = median(×);
|
||||
let throughput = moved_expected as f64 / (med / 1_000_000.0);
|
||||
runner.record(
|
||||
name,
|
||||
"FLATTEN apply: apply_flatten_updates (per-entity update_entity publish)",
|
||||
"us",
|
||||
times,
|
||||
Some((throughput, "entities/s")),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("\nInitializing OpenCADStudio Command Benchmarks...");
|
||||
let mut runner = BenchmarkRunner::new(
|
||||
@@ -252,6 +421,8 @@ fn main() {
|
||||
|
||||
bench_explode_geometry(&mut runner);
|
||||
bench_explode_scene_apply(&mut runner);
|
||||
bench_flatten_plan(&mut runner);
|
||||
bench_flatten_scene_apply(&mut runner);
|
||||
|
||||
runner.finish();
|
||||
}
|
||||
Reference in new issue
Block a user