From 846f15f09f67f9004e46506e82ca80b78ded08d4 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 6 Oct 2025 13:04:04 +0200 Subject: [PATCH 1/5] Add simple test script for testing out widely branched transform hierarchies With lots of entities ofc. --- tests/python/many_entities/main.py | 22 ----- tests/python/many_entity_transforms/main.py | 95 +++++++++++++++++++++ 2 files changed, 95 insertions(+), 22 deletions(-) delete mode 100644 tests/python/many_entities/main.py create mode 100644 tests/python/many_entity_transforms/main.py diff --git a/tests/python/many_entities/main.py b/tests/python/many_entities/main.py deleted file mode 100644 index 52a45ca7912b..000000000000 --- a/tests/python/many_entities/main.py +++ /dev/null @@ -1,22 +0,0 @@ -from __future__ import annotations - -import argparse -import math - -import rerun as rr - - -def main() -> None: - parser = argparse.ArgumentParser(description="Simple benchmark for many individual entities.") - rr.script_add_args(parser) - args = parser.parse_args() - - rr.script_setup(args, "rerun_example_benchmark_many_entities") - - for i in range(1000): - f = i * 0.1 - rr.log("i" + str(i), rr.Points3D([math.sin(f), f, math.cos(f)])) - - -if __name__ == "__main__": - main() diff --git a/tests/python/many_entity_transforms/main.py b/tests/python/many_entity_transforms/main.py new file mode 100644 index 000000000000..c81fa8a62434 --- /dev/null +++ b/tests/python/many_entity_transforms/main.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +import argparse + +import rerun as rr +import rerun.blueprint as rrb + + +def main() -> None: + parser = argparse.ArgumentParser(description="Simple benchmark for many transforms over time & space.") + rr.script_add_args(parser) + + parser.add_argument("--branching-factor", type=int, default=2, help="How many children each node has") + parser.add_argument("--hierarchy-depth", type=int, default=10, help="How many levels of hierarchy we want") + parser.add_argument( + "--transforms-every-n-levels", type=int, default=2, help="At which level in the hierarchies we add transforms" + ) + parser.add_argument( + "--num-timestamps", + type=int, + default=100, + help="Number of timestamps to log. Stamps shift for each entity a bit.", + ) + parser.add_argument("--no-points-on-leafs", action="store_true", help="If set, don't log a point at each leaf") + parser.add_argument( + "--num-views", type=int, default=6, help="Number of 3D views to create (each will use a different origin)" + ) + + args = parser.parse_args() + + rr.script_setup(args, "rerun_example_benchmark_many_transforms") + rr.set_time("sim_time", duration=0) + + entity_paths = [] + call_id = 0 + + def log_hierarchy(entity_path: str, level: int): + nonlocal call_id + call_id += 1 + entity_paths.append(entity_path) + + # Add a transform at every 'transforms_every_n_levels' level except root + if level > 0 and level % args.transforms_every_n_levels == 0: + # Add a static transform that has to be combined in to stress the per-timestamp transform resolve. + rr.log( + entity_path, + # Have to be careful to not override all other transforms, therefore, use `from_fields`. + rr.Transform3D.from_fields( # + mat3x3=[ + [1.0 + level * 0.1, 0.0, 0.0], # + [0.0, 1.0 + level * 0.1, 0.0], + [0.0, 0.0, 1.0 + level * 0.1], + ] + ), + static=True, + ) + + # Add a transforms that changes for each timestamp. + for i in range(args.num_timestamps): + call_id_factor = call_id * 0.02 + rr.set_time("sim_time", duration=i + call_id_factor) + rr.log( + entity_path, + rr.Transform3D( + translation=[i * 0.1 * level + call_id_factor, call_id_factor * level, 0.0], + rotation_axis_angle=rr.RotationAxisAngle(axis=(0.0, 1.0, 0.0), degrees=i * 0.1), + ), + ) + + if level == args.hierarchy_depth: + if not args.no_points_on_leafs: + # Log a single point at the leaf + rr.set_time("sim_time", duration=0) + rr.log(entity_path, rr.Points3D([[0.0, 0.0, 0.0]])) + return + + for i in range(args.branching_factor): + child_path = f"{entity_path}/{i}_at_{level}" + log_hierarchy(child_path, level + 1) + + log_hierarchy("root", 0) + + # All views display all entities. + rr.send_blueprint( + rrb.Blueprint( + rrb.Grid( + contents=[rrb.Spatial3DView(origin=path, contents="/**") for path in entity_paths[: args.num_views]] + ), + collapse_panels=True, # Collapse panels, so we perf is mostly about the data & the views. + ) + ) + + +if __name__ == "__main__": + main() From 93311fa1eb15ddbe14ad107ad1f0a0c7bf1b6afb Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 6 Oct 2025 14:40:00 +0200 Subject: [PATCH 2/5] add missing profiling scope --- crates/viewer/re_viewport_blueprint/src/view_contents.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/viewer/re_viewport_blueprint/src/view_contents.rs b/crates/viewer/re_viewport_blueprint/src/view_contents.rs index ea475369cbb9..355a604539b3 100644 --- a/crates/viewer/re_viewport_blueprint/src/view_contents.rs +++ b/crates/viewer/re_viewport_blueprint/src/view_contents.rs @@ -462,6 +462,8 @@ impl<'a> DataQueryPropertyResolver<'a> { parent_visible: bool, parent_interactive: bool, ) { + // This is called very frequently, don't put a profile scope here. + let Some(node) = query_result.tree.lookup_node_mut(handle) else { return; }; @@ -596,7 +598,7 @@ impl<'a> DataQueryPropertyResolver<'a> { query_result: &mut DataQueryResult, view_states: &mut ViewStates, ) { - // This is called very frequently, don't put a profile scope here. + re_tracing::profile_function!(); if let Some(root) = query_result.tree.root_handle() { let class = self.view.class(view_class_registry); From b972e6461268af7bd0bdbb4c569c0e4638cff07f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 6 Oct 2025 14:46:17 +0200 Subject: [PATCH 3/5] py lint, better arg name --- tests/python/many_entity_transforms/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/python/many_entity_transforms/main.py b/tests/python/many_entity_transforms/main.py index c81fa8a62434..2a5ccd5074da 100644 --- a/tests/python/many_entity_transforms/main.py +++ b/tests/python/many_entity_transforms/main.py @@ -21,7 +21,7 @@ def main() -> None: default=100, help="Number of timestamps to log. Stamps shift for each entity a bit.", ) - parser.add_argument("--no-points-on-leafs", action="store_true", help="If set, don't log a point at each leaf") + parser.add_argument("--transforms-only", action="store_true", help="If set, don't log a point at each leaf") parser.add_argument( "--num-views", type=int, default=6, help="Number of 3D views to create (each will use a different origin)" ) @@ -34,7 +34,7 @@ def main() -> None: entity_paths = [] call_id = 0 - def log_hierarchy(entity_path: str, level: int): + def log_hierarchy(entity_path: str, level: int) -> None: nonlocal call_id call_id += 1 entity_paths.append(entity_path) @@ -68,7 +68,7 @@ def log_hierarchy(entity_path: str, level: int): ) if level == args.hierarchy_depth: - if not args.no_points_on_leafs: + if not args.transforms_only: # Log a single point at the leaf rr.set_time("sim_time", duration=0) rr.log(entity_path, rr.Points3D([[0.0, 0.0, 0.0]])) From 93d22f3b306212b9b3c39d44b70acd4c9e443089 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 6 Oct 2025 21:48:10 +0200 Subject: [PATCH 4/5] Update tests/python/many_entity_transforms/main.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/python/many_entity_transforms/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/many_entity_transforms/main.py b/tests/python/many_entity_transforms/main.py index 2a5ccd5074da..e404bde4f40a 100644 --- a/tests/python/many_entity_transforms/main.py +++ b/tests/python/many_entity_transforms/main.py @@ -86,7 +86,7 @@ def log_hierarchy(entity_path: str, level: int) -> None: rrb.Grid( contents=[rrb.Spatial3DView(origin=path, contents="/**") for path in entity_paths[: args.num_views]] ), - collapse_panels=True, # Collapse panels, so we perf is mostly about the data & the views. + collapse_panels=True, # Collapse panels, so perf is mostly about the data & the views. ) ) From 98fedda101324e1d02002e540a90427fc2de6bcb Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 6 Oct 2025 21:48:17 +0200 Subject: [PATCH 5/5] Update tests/python/many_entity_transforms/main.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/python/many_entity_transforms/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/many_entity_transforms/main.py b/tests/python/many_entity_transforms/main.py index e404bde4f40a..c527470b37af 100644 --- a/tests/python/many_entity_transforms/main.py +++ b/tests/python/many_entity_transforms/main.py @@ -55,7 +55,7 @@ def log_hierarchy(entity_path: str, level: int) -> None: static=True, ) - # Add a transforms that changes for each timestamp. + # Add a transform that changes for each timestamp. for i in range(args.num_timestamps): call_id_factor = call_id * 0.02 rr.set_time("sim_time", duration=i + call_id_factor)