Skip to content

Commit

Permalink
Primary caching 5: 2D & 3D point clouds (#4681)
Browse files Browse the repository at this point in the history
Integrates the cached APIs with the 2D & 3D spatial views, which is a
pretty tough thing to do because there's a lot of abstraction going on
in there.

`main` vs. cache disabled vs. cache enable (5950X, Arch):
```
group                        main                                    primcache_5_uncached                        primcache_5_cached                  
-----                        ----                                    --------------------                        ------------------                  
Points3D/load_all            1.68     10.1±0.14ms  94.2 MElem/sec        1.00      6.0±0.07ms 157.9 MElem/sec    1.01      6.1±0.06ms 155.7 MElem/sec
Points3D/load_colors         1.44      3.8±0.02ms 252.6 MElem/sec        1.00      2.6±0.05ms 364.0 MElem/sec    1.07      2.8±0.06ms 339.5 MElem/sec
Points3D/load_picking_ids    15.16  1859.6±7.01µs 512.9 MElem/sec        1.01    124.3±3.92µs   7.5 GElem/sec    1.00    122.7±3.86µs   7.6 GElem/sec 
Points3D/load_positions      2.29    420.1±0.76µs   2.2 GElem/sec        1.03    189.3±7.44µs   4.9 GElem/sec    1.00    183.4±5.56µs   5.1 GElem/sec 
Points3D/load_radii          1.46      3.3±0.04ms 290.1 MElem/sec        1.05      2.4±0.03ms 404.8 MElem/sec    1.00      2.2±0.00ms 423.9 MElem/sec
Points3D/query_archetype     2.51    676.1±7.59ns        ? ?/sec     15859.98      4.3±0.06ms         ? ?/sec    1.00    268.9±3.39ns         ? ?/sec 
```

---

Part of the primary caching series of PR (index search, joins,
deserialization):
- #4592
- #4593
- #4659
- #4680 
- #4681
- #4698
- #4711
- #4712
- #4721 
- #4726
  • Loading branch information
teh-cmc authored Jan 10, 2024
1 parent c626364 commit 11688cf
Show file tree
Hide file tree
Showing 11 changed files with 630 additions and 248 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/re_space_view_spatial/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ re_format.workspace = true
re_log_types.workspace = true
re_log.workspace = true
re_query.workspace = true
re_query_cache.workspace = true
re_renderer = { workspace = true, features = ["import-gltf", "import-obj"] }
re_types = { workspace = true, features = ["ecolor", "glam", "image"] }
re_tracing.workspace = true
Expand Down
223 changes: 144 additions & 79 deletions crates/re_space_view_spatial/benches/bench_points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
use re_data_store::{DataStore, LatestAtQuery};
use re_log_types::{DataRow, EntityPath, RowId, TimeInt, TimePoint, Timeline};
use re_space_view_spatial::LoadedPoints;
use re_space_view_spatial::{LoadedPoints, Points3DComponentData};
use re_types::{
archetypes::Points3D,
components::{Color, InstanceKey, Position3D},
components::{ClassId, Color, InstanceKey, KeypointId, Position3D, Radius, Text},
Loggable as _,
};
use re_viewer_context::Annotations;
Expand All @@ -18,12 +18,21 @@ criterion::criterion_group!(benches, bench_points);

// ---

#[cfg(not(debug_assertions))]
const NUM_POINTS: usize = 1_000_000;

// `cargo test` also runs the benchmark setup code, so make sure they run quickly:
#[cfg(debug_assertions)]
const NUM_POINTS: usize = 10;
mod constants {
pub const NUM_POINTS: usize = 10;
pub const CACHED: &[bool] = &[true];
}

#[cfg(not(debug_assertions))]
mod constants {
pub const NUM_POINTS: usize = 1_000_000;
pub const CACHED: &[bool] = &[false, true];
}

#[allow(clippy::wildcard_imports)]
use self::constants::*;

// ---

Expand Down Expand Up @@ -51,88 +60,144 @@ fn bench_points(c: &mut criterion::Criterion) {
};

let latest_at = LatestAtQuery::latest(timeline);
let at = latest_at.at;
let latest_at = re_query_cache::AnyQuery::from(latest_at);
let annotations = Annotations::missing();

{
let mut group = c.benchmark_group("Points3D");
group.bench_function("query_archetype", |b| {
b.iter(|| {
let arch_view =
re_query::query_archetype::<Points3D>(&store, &latest_at, &ent_path).unwrap();
assert_eq!(arch_view.num_instances(), NUM_POINTS);
arch_view
});
});
}

let arch_view = re_query::query_archetype::<Points3D>(&store, &latest_at, &ent_path).unwrap();
assert_eq!(arch_view.num_instances(), NUM_POINTS);

{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function("load_all", |b| {
b.iter(|| {
let points =
LoadedPoints::load(&arch_view, &ent_path, latest_at.at, &annotations).unwrap();
assert_eq!(points.positions.len(), NUM_POINTS);
assert_eq!(points.colors.len(), NUM_POINTS);
assert_eq!(points.radii.len(), NUM_POINTS); // NOTE: we don't log radii, but we should get a list of defaults!
points
});
});
fn bench_name(cached: bool, name: &str) -> String {
format!("{name}/cached={cached}")
}

{
for cached in CACHED {
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function("load_positions", |b| {
group.bench_function(bench_name(*cached, "query_archetype"), |b| {
b.iter(|| {
let positions = LoadedPoints::load_positions(&arch_view).unwrap();
assert_eq!(positions.len(), NUM_POINTS);
positions
re_query_cache::query_archetype_pov1_comp5::<
Points3D,
Position3D,
Color,
Radius,
Text,
KeypointId,
ClassId,
_,
>(
*cached,
&store,
&latest_at,
&ent_path,
|(_, keys, _, _, _, _, _, _)| {
assert_eq!(keys.as_slice().len(), NUM_POINTS);
},
)
.unwrap();
});
});
}

{
let points = LoadedPoints::load(&arch_view, &ent_path, latest_at.at, &annotations).unwrap();

let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function("load_colors", |b| {
b.iter(|| {
let colors =
LoadedPoints::load_colors(&arch_view, &ent_path, &points.annotation_infos)
.unwrap();
assert_eq!(colors.len(), NUM_POINTS);
colors
});
});
}

// NOTE: we don't log radii!
{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function("load_radii", |b| {
b.iter(|| {
let radii = LoadedPoints::load_radii(&arch_view, &ent_path).unwrap();
assert_eq!(radii.len(), NUM_POINTS);
radii
});
});
}

{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function("load_picking_ids", |b| {
b.iter(|| {
let picking_ids = LoadedPoints::load_picking_ids(&arch_view);
assert_eq!(picking_ids.len(), NUM_POINTS);
picking_ids
});
});
for cached in CACHED {
re_query_cache::query_archetype_pov1_comp5::<
Points3D,
Position3D,
Color,
Radius,
Text,
KeypointId,
ClassId,
_,
>(
*cached,
&store,
&latest_at,
&ent_path,
|(_, instance_keys, positions, colors, radii, labels, keypoint_ids, class_ids)| {
let data = Points3DComponentData {
instance_keys: instance_keys.as_slice(),
positions: positions.as_slice(),
colors: colors.as_slice(),
radii: radii.as_slice(),
labels: labels.as_slice(),
keypoint_ids: keypoint_ids
.iter()
.any(Option::is_some)
.then_some(keypoint_ids.as_slice()),
class_ids: class_ids
.iter()
.any(Option::is_some)
.then_some(class_ids.as_slice()),
};
assert_eq!(data.instance_keys.len(), NUM_POINTS);

{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function(bench_name(*cached, "load_all"), |b| {
b.iter(|| {
let points = LoadedPoints::load(&data, &ent_path, at, &annotations);
assert_eq!(points.positions.len(), NUM_POINTS);
assert_eq!(points.colors.len(), NUM_POINTS);
assert_eq!(points.radii.len(), NUM_POINTS); // NOTE: we don't log radii, but we should get a list of defaults!
points
});
});
}

{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function(bench_name(*cached, "load_positions"), |b| {
b.iter(|| {
let positions = LoadedPoints::load_positions(&data);
assert_eq!(positions.len(), NUM_POINTS);
positions
});
});
}

{
let points = LoadedPoints::load(&data, &ent_path, at, &annotations);

let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function(bench_name(*cached, "load_colors"), |b| {
b.iter(|| {
let colors = LoadedPoints::load_colors(
&data,
&ent_path,
&points.annotation_infos,
);
assert_eq!(colors.len(), NUM_POINTS);
colors
});
});
}

// NOTE: we don't log radii!
{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function(bench_name(*cached, "load_radii"), |b| {
b.iter(|| {
let radii = LoadedPoints::load_radii(&data, &ent_path);
assert_eq!(radii.len(), NUM_POINTS);
radii
});
});
}

{
let mut group = c.benchmark_group("Points3D");
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _));
group.bench_function(bench_name(*cached, "load_picking_ids"), |b| {
b.iter(|| {
let picking_ids = LoadedPoints::load_picking_ids(&data);
assert_eq!(picking_ids.len(), NUM_POINTS);
picking_ids
});
});
}
},
)
.unwrap();
}
}
2 changes: 1 addition & 1 deletion crates/re_space_view_spatial/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub use space_view_2d::SpatialSpaceView2D;
pub use space_view_3d::SpatialSpaceView3D;

#[doc(hidden)] // Public for benchmarks
pub use visualizers::LoadedPoints;
pub use visualizers::{LoadedPoints, Points3DComponentData};

// ---

Expand Down
Loading

0 comments on commit 11688cf

Please sign in to comment.