Skip to content

Commit

Permalink
A nice speed up of 3D points clouds by ~69% (rerun-io#3114)
Browse files Browse the repository at this point in the history
### What
On native, use `rayon` to parallelize the gathering of positions, radii,
colors, and picking ids. Of course, this only works on native. I also
noticed that we spent a lot of time generating identical annotation
infos for all the points, so I happy-pathed that.

Test: `cargo rerun-release ../opf.rrd --profile`, looking at just the 3D
view, averaged over ~30 frames:

Full frame 37.0ms -> 26.6ms ≈ 39% faster

`Points3DPart`: 25.7ms -> 15.2ms ≈ 69% faster

Before:
![Screenshot 2023-08-27 at 17 39
52](https://github.com/rerun-io/rerun/assets/1148717/95b2de1b-ab21-489b-8e05-039e8de50692)

After:

![image](https://github.com/rerun-io/rerun/assets/1148717/2e0f7dc7-ccce-4cd8-9157-162bb642c795)



### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested
[demo.rerun.io](https://demo.rerun.io/pr/3114/examples/structure_from_motion/)
(if applicable)

- [PR Build Summary](https://build.rerun.io/pr/3114)
- [Docs
preview](https://rerun.io/preview/d70a51a580149f974aec0c089fb8f899e132c518/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/d70a51a580149f974aec0c089fb8f899e132c518/examples)
<!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW--><!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://ref.rerun.io/dev/bench/)
- [Wasm size tracking](https://ref.rerun.io/dev/sizes/)
  • Loading branch information
emilk authored Aug 28, 2023
1 parent 2e28c5d commit 5622677
Show file tree
Hide file tree
Showing 21 changed files with 150 additions and 72 deletions.
3 changes: 3 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# `cargo rerun` is short a convenient shorthand, skipping the web viewer.
rerun = "run --package rerun-cli --no-default-features --features native_viewer --"

# like `rerun`, but with --release
rerun-release = "run --package rerun-cli --no-default-features --features native_viewer --release --"

# `cargo rerun-web` is short a convenient shorthand for building & starting the web viewer.
rerun-web = "run --package rerun-cli --no-default-features --features web_viewer -- --web-viewer"

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

9 changes: 6 additions & 3 deletions crates/re_query/src/archetype_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,16 +314,19 @@ impl<A: Archetype> ArchetypeView<A> {
pub fn iter_optional_component<'a, C: Component + Clone + 'a>(
&'a self,
) -> DeserializationResult<impl Iterator<Item = Option<C>> + '_> {
re_tracing::profile_function!();
re_tracing::profile_function!(C::name());

let component = self.components.get(&C::name());

if let Some(component) = component {
let primary_instance_key_iter = self.iter_instance_keys();

let mut component_instance_key_iter = component.iter_instance_keys();

let component_value_iter =
C::try_from_arrow_opt(component.values.as_arrow_ref())?.into_iter();
let component_value_iter = {
re_tracing::profile_scope!("try_from_arrow_opt", C::name());
C::try_from_arrow_opt(component.values.as_arrow_ref())?.into_iter()
};

let next_component_instance_key = component_instance_key_iter.next();

Expand Down
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 @@ -42,6 +42,7 @@ itertools.workspace = true
macaw = { workspace = true, features = ["with_serde"] }
nohash-hasher.workspace = true
parking_lot.workspace = true
rayon.workspace = true
serde = "1"
smallvec = { workspace = true, features = ["serde"] }
vec1.workspace = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ impl ViewContextSystem for AnnotationSceneContext {
ctx: &mut re_viewer_context::ViewerContext<'_>,
query: &re_viewer_context::ViewQuery<'_>,
) {
re_tracing::profile_function!();
self.0.load(
ctx,
&query.latest_at_query(),
Expand Down
1 change: 1 addition & 0 deletions crates/re_space_view_spatial/src/contexts/depth_offsets.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::{BTreeMap, BTreeSet};

use nohash_hasher::IntMap;

use re_log_types::EntityPathHash;
use re_types::{components::DrawOrder, Loggable as _};
use re_viewer_context::{ArchetypeDefinition, ViewContextSystem};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl ViewContextSystem for SharedRenderBuilders {
ctx: &mut re_viewer_context::ViewerContext<'_>,
_query: &re_viewer_context::ViewQuery<'_>,
) {
re_tracing::profile_function!();
self.lines = Mutex::new(Some(
LineStripSeriesBuilder::new(ctx.render_ctx)
.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ fn transform_at(
pinhole_image_plane_distance: impl Fn(&EntityPath) -> f32,
encountered_pinhole: &mut Option<EntityPath>,
) -> Result<Option<glam::Affine3A>, UnreachableTransformReason> {
re_tracing::profile_function!();

let pinhole = store.query_latest_component::<Pinhole>(entity_path, query);
if pinhole.is_some() {
if encountered_pinhole.is_some() {
Expand Down
4 changes: 2 additions & 2 deletions crates/re_space_view_spatial/src/parts/arrows3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use re_types::{
Archetype as _,
};
use re_viewer_context::{
ArchetypeDefinition, ResolvedAnnotationInfo, SpaceViewSystemExecutionError,
ArchetypeDefinition, ResolvedAnnotationInfos, SpaceViewSystemExecutionError,
ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext,
};

Expand Down Expand Up @@ -41,7 +41,7 @@ impl Arrows3DPart {
arch_view: &'a ArchetypeView<Arrows3D>,
instance_path_hashes: &'a [InstancePathHash],
colors: &'a [egui::Color32],
annotation_infos: &'a [ResolvedAnnotationInfo],
annotation_infos: &'a ResolvedAnnotationInfos,
world_from_obj: glam::Affine3A,
) -> Result<impl Iterator<Item = UiLabel> + 'a, QueryError> {
let labels = itertools::izip!(
Expand Down
4 changes: 2 additions & 2 deletions crates/re_space_view_spatial/src/parts/lines2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use re_types::{
Archetype as _,
};
use re_viewer_context::{
ArchetypeDefinition, ResolvedAnnotationInfo, SpaceViewSystemExecutionError,
ArchetypeDefinition, ResolvedAnnotationInfos, SpaceViewSystemExecutionError,
ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext,
};

Expand Down Expand Up @@ -41,7 +41,7 @@ impl Lines2DPart {
arch_view: &'a ArchetypeView<LineStrips2D>,
instance_path_hashes: &'a [InstancePathHash],
colors: &'a [egui::Color32],
annotation_infos: &'a [ResolvedAnnotationInfo],
annotation_infos: &'a ResolvedAnnotationInfos,
) -> Result<impl Iterator<Item = UiLabel> + 'a, QueryError> {
let labels = itertools::izip!(
annotation_infos.iter(),
Expand Down
4 changes: 2 additions & 2 deletions crates/re_space_view_spatial/src/parts/lines3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use re_types::{
Archetype as _,
};
use re_viewer_context::{
ArchetypeDefinition, ResolvedAnnotationInfo, SpaceViewSystemExecutionError,
ArchetypeDefinition, ResolvedAnnotationInfos, SpaceViewSystemExecutionError,
ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext,
};

Expand Down Expand Up @@ -41,7 +41,7 @@ impl Lines3DPart {
arch_view: &'a ArchetypeView<LineStrips3D>,
instance_path_hashes: &'a [InstancePathHash],
colors: &'a [egui::Color32],
annotation_infos: &'a [ResolvedAnnotationInfo],
annotation_infos: &'a ResolvedAnnotationInfos,
world_from_obj: glam::Affine3A,
) -> Result<impl Iterator<Item = UiLabel> + 'a, QueryError> {
re_tracing::profile_function!();
Expand Down
17 changes: 10 additions & 7 deletions crates/re_space_view_spatial/src/parts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use re_types::datatypes::{KeypointId, KeypointPair};
use re_types::Archetype;
use re_viewer_context::SpaceViewClassRegistryError;
use re_viewer_context::{
auto_color, Annotations, DefaultColor, ResolvedAnnotationInfo, SpaceViewSystemRegistry,
auto_color, Annotations, DefaultColor, ResolvedAnnotationInfos, SpaceViewSystemRegistry,
ViewPartCollection, ViewQuery,
};

Expand Down Expand Up @@ -105,7 +105,7 @@ pub fn picking_id_from_instance_key(
pub fn process_colors<'a, A: Archetype>(
arch_view: &'a re_query::ArchetypeView<A>,
ent_path: &'a EntityPath,
annotation_infos: &'a [ResolvedAnnotationInfo],
annotation_infos: &'a ResolvedAnnotationInfos,
) -> Result<impl Iterator<Item = egui::Color32> + 'a, re_query::QueryError> {
re_tracing::profile_function!();
let default_color = DefaultColor::EntityPath(ent_path);
Expand Down Expand Up @@ -153,7 +153,7 @@ fn process_annotations_and_keypoints<Primary, A: Archetype>(
arch_view: &re_query::ArchetypeView<A>,
annotations: &Arc<Annotations>,
mut primary_into_position: impl FnMut(&Primary) -> glam::Vec3,
) -> Result<(Vec<ResolvedAnnotationInfo>, Keypoints), re_query::QueryError>
) -> Result<(ResolvedAnnotationInfos, Keypoints), re_query::QueryError>
where
Primary: re_types::Component + Clone + Default,
{
Expand All @@ -168,8 +168,9 @@ where
let resolved_annotation = annotations
.resolved_class_description(None)
.annotation_info();

return Ok((
vec![resolved_annotation; arch_view.num_instances()],
ResolvedAnnotationInfos::Same(arch_view.num_instances(), resolved_annotation),
keypoints,
));
}
Expand All @@ -194,7 +195,7 @@ where
})
.collect();

Ok((annotation_info, keypoints))
Ok((ResolvedAnnotationInfos::Many(annotation_info), keypoints))
}

#[derive(Clone)]
Expand Down Expand Up @@ -224,12 +225,14 @@ pub struct UiLabel {
pub fn load_keypoint_connections(
ent_context: &SpatialSceneEntityContext<'_>,
ent_path: &re_data_store::EntityPath,
keypoints: Keypoints,
keypoints: &Keypoints,
) {
if keypoints.is_empty() {
return;
}

re_tracing::profile_function!();

// Generate keypoint connections if any.
let mut line_builder = ent_context.shared_render_builders.lines();
let mut line_batch = line_builder
Expand All @@ -240,7 +243,7 @@ pub fn load_keypoint_connections(
for ((class_id, _time), keypoints_in_class) in keypoints {
let resolved_class_description = ent_context
.annotations
.resolved_class_description(Some(class_id));
.resolved_class_description(Some(*class_id));

let Some(class_description) = resolved_class_description.class_description else {
continue;
Expand Down
6 changes: 3 additions & 3 deletions crates/re_space_view_spatial/src/parts/points2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use re_types::{
Archetype,
};
use re_viewer_context::{
ArchetypeDefinition, ResolvedAnnotationInfo, SpaceViewSystemExecutionError,
ArchetypeDefinition, ResolvedAnnotationInfos, SpaceViewSystemExecutionError,
ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext,
};

Expand Down Expand Up @@ -41,7 +41,7 @@ impl Points2DPart {
arch_view: &'a ArchetypeView<Points2D>,
instance_path_hashes: &'a [InstancePathHash],
colors: &'a [egui::Color32],
annotation_infos: &'a [ResolvedAnnotationInfo],
annotation_infos: &'a ResolvedAnnotationInfos,
) -> Result<impl Iterator<Item = UiLabel> + 'a, QueryError> {
let labels = itertools::izip!(
annotation_infos.iter(),
Expand Down Expand Up @@ -167,7 +167,7 @@ impl Points2DPart {
}
};

load_keypoint_connections(ent_context, ent_path, keypoints);
load_keypoint_connections(ent_context, ent_path, &keypoints);

self.data.extend_bounding_box_with_points(
arch_view
Expand Down
92 changes: 55 additions & 37 deletions crates/re_space_view_spatial/src/parts/points3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ use re_types::{
Archetype as _,
};
use re_viewer_context::{
ArchetypeDefinition, ResolvedAnnotationInfo, SpaceViewSystemExecutionError,
ArchetypeDefinition, ResolvedAnnotationInfos, SpaceViewSystemExecutionError,
ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext,
};

use itertools::Itertools as _;

use crate::{
contexts::{EntityDepthOffsets, SpatialSceneEntityContext},
parts::{
Expand Down Expand Up @@ -41,7 +43,7 @@ impl Points3DPart {
arch_view: &'a ArchetypeView<Points3D>,
instance_path_hashes: &'a [InstancePathHash],
colors: &'a [egui::Color32],
annotation_infos: &'a [ResolvedAnnotationInfo],
annotation_infos: &'a ResolvedAnnotationInfos,
world_from_obj: glam::Affine3A,
) -> Result<impl Iterator<Item = UiLabel> + 'a, QueryError> {
re_tracing::profile_function!();
Expand Down Expand Up @@ -122,36 +124,34 @@ impl Points3DPart {
.outline_mask_ids(ent_context.highlight.overall)
.picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64()));

let point_positions = arch_view
.iter_required_component::<Point3D>()?
.map(glam::Vec3::from);

let picking_instance_ids = arch_view
.iter_instance_keys()
.map(picking_id_from_instance_key);

let point_positions: Vec<glam::Vec3> = {
re_tracing::profile_scope!("collect_positions");
point_positions.collect()
};

let radii: Vec<_> = {
re_tracing::profile_scope!("collect_radii");
radii.collect()
};

let colors: Vec<_> = {
re_tracing::profile_scope!("collect_colors");
colors.collect()
};
let (positions, radii, colors, picking_instance_ids) = join4(
|| {
re_tracing::profile_scope!("positions");
arch_view
.iter_required_component::<Point3D>()
.map(|p| p.map(glam::Vec3::from).collect_vec())
},
|| {
re_tracing::profile_scope!("radii");
radii.collect_vec()
},
|| {
re_tracing::profile_scope!("colors");
colors.collect_vec()
},
|| {
re_tracing::profile_scope!("picking_ids");
arch_view
.iter_instance_keys()
.map(picking_id_from_instance_key)
.collect_vec()
},
);

let picking_instance_ids: Vec<_> = {
re_tracing::profile_scope!("collect_picking_instance_ids");
picking_instance_ids.collect()
};
let positions = positions?;

let mut point_range_builder =
point_batch.add_points(&point_positions, &radii, &colors, &picking_instance_ids);
point_batch.add_points(&positions, &radii, &colors, &picking_instance_ids);

// Determine if there's any sub-ranges that need extra highlighting.
{
Expand All @@ -170,16 +170,14 @@ impl Points3DPart {
}
}
}

self.data.extend_bounding_box_with_points(
positions.iter().copied(),
ent_context.world_from_obj,
);
}

load_keypoint_connections(ent_context, ent_path, keypoints);

self.data.extend_bounding_box_with_points(
arch_view
.iter_required_component::<Point3D>()?
.map(glam::Vec3::from),
ent_context.world_from_obj,
);
load_keypoint_connections(ent_context, ent_path, &keypoints);

Ok(())
}
Expand Down Expand Up @@ -219,3 +217,23 @@ impl ViewPartSystem for Points3DPart {
self
}
}

/// Run 4 things in parallel
fn join4<A: Send, B: Send, C: Send, D: Send>(
a: impl FnOnce() -> A + Send,
b: impl FnOnce() -> B + Send,
c: impl FnOnce() -> C + Send,
d: impl FnOnce() -> D + Send,
) -> (A, B, C, D) {
#[cfg(not(target_arch = "wasm32"))]
{
re_tracing::profile_function!();
let ((a, b), (c, d)) = rayon::join(|| rayon::join(a, b), || rayon::join(c, d));
(a, b, c, d)
}

#[cfg(target_arch = "wasm32")]
{
(a(), b(), c(), d())
}
}
2 changes: 2 additions & 0 deletions crates/re_space_view_spatial/src/space_view_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ impl SpaceViewClass for SpatialSpaceView3D {
query: &ViewQuery<'_>,
draw_data: Vec<re_renderer::QueueableDrawData>,
) -> Result<(), SpaceViewSystemExecutionError> {
re_tracing::profile_function!();

state.scene_bbox = calculate_bounding_box(parts, &mut state.scene_bbox_accum);
state.scene_num_primitives = view_ctx
.get::<PrimitiveCounter>()?
Expand Down
5 changes: 2 additions & 3 deletions crates/re_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ testing = []
[dependencies]
# Rerun
re_error.workspace = true
re_string_interner.workspace = true
re_tracing.workspace = true

# External
anyhow.workspace = true
Expand All @@ -66,9 +68,6 @@ glam = { workspace = true, optional = true }
macaw = { workspace = true, optional = true }
serde = { version = "1", optional = true, features = ["derive", "rc"] }

# Rerun
re_string_interner.workspace = true
re_tracing.workspace = true

[dev-dependencies]

Expand Down
Loading

0 comments on commit 5622677

Please sign in to comment.