From 6e6131839b10229c59950fef827a64a9722fbbea Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Tue, 2 Jul 2024 18:02:28 +0200 Subject: [PATCH 01/16] added initial benchmarks, similar to bevy_xpbd --- benches_common/Cargo.toml | 9 +++++ benches_common/src/lib.rs | 63 ++++++++++++++++++++++++++++++++++ bevy_rapier3d/Cargo.toml | 6 ++++ bevy_rapier3d/benches/cubes.rs | 47 +++++++++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 benches_common/Cargo.toml create mode 100644 benches_common/src/lib.rs create mode 100644 bevy_rapier3d/benches/cubes.rs diff --git a/benches_common/Cargo.toml b/benches_common/Cargo.toml new file mode 100644 index 00000000..e3068d18 --- /dev/null +++ b/benches_common/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "benches_common" +version = "0.1.0" +edition = "2021" + +[dependencies] +bevy = { version = "0.14.0-rc.3", default-features = false } +bevy_rapier3d = { path = "../bevy_rapier3d", default-features = false } +criterion = "0.5" diff --git a/benches_common/src/lib.rs b/benches_common/src/lib.rs new file mode 100644 index 00000000..70aa35bf --- /dev/null +++ b/benches_common/src/lib.rs @@ -0,0 +1,63 @@ +use bevy::{ + app::PluginsState, + prelude::*, + render::{ + settings::{RenderCreation, WgpuSettings}, + RenderPlugin, + }, + scene::ScenePlugin, + time::TimeUpdateStrategy, +}; +use bevy_rapier3d::prelude::*; +use criterion::{measurement::Measurement, BatchSize, Bencher}; + +pub fn bench_app( + bencher: &mut Bencher<'_, M>, + steps: u32, + setup: impl Fn(&mut App), +) { + bencher.iter_batched_ref( + move || { + let mut app = App::new(); + + app.add_plugins(( + WindowPlugin::default(), + MinimalPlugins, + AssetPlugin::default(), + ScenePlugin, + RenderPlugin { + render_creation: RenderCreation::Automatic(WgpuSettings { + backends: None, + ..Default::default() + }), + ..Default::default() + }, + ImagePlugin::default(), + HierarchyPlugin, + TransformPlugin, + RapierPhysicsPlugin::<()>::default(), + )); + + // 60 physics + app.insert_resource(TimeUpdateStrategy::ManualDuration( + std::time::Duration::from_secs_f32(1f32 / 60f32), + )); + + setup(&mut app); + + while app.plugins_state() != PluginsState::Ready { + bevy::tasks::tick_global_task_pools_on_main_thread(); + } + + app.finish(); + app.cleanup(); + app + }, + move |app| { + for _ in 0..steps { + app.update(); + } + }, + BatchSize::PerIteration, + ); +} diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index 000b6c03..c817f66c 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -53,6 +53,7 @@ log = "0.4" serde = { version = "1", features = ["derive"], optional = true } [dev-dependencies] +benches_common = { path = "../benches_common" } bevy = { version = "0.14.0-rc.3", default-features = false, features = [ "x11", "tonemapping_luts", @@ -60,7 +61,12 @@ bevy = { version = "0.14.0-rc.3", default-features = false, features = [ ] } approx = "0.5.1" glam = { version = "0.27", features = ["approx"] } +criterion = { version = "0.5", features = ["html_reports"] } [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs features = ["debug-render-3d", "serde-serialize"] + +[[bench]] +name = "cubes" +harness = false diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs new file mode 100644 index 00000000..0377f21d --- /dev/null +++ b/bevy_rapier3d/benches/cubes.rs @@ -0,0 +1,47 @@ +use std::time::Duration; + +use benches_common::bench_app; +use bevy::prelude::*; +use bevy_rapier3d::math::*; +use bevy_rapier3d::prelude::*; +use criterion::{criterion_group, criterion_main, Criterion}; + +fn setup_cubes(app: &mut App, size: u32) { + app.add_systems(Startup, move |mut commands: Commands| { + commands.spawn(( + RigidBody::Fixed, + Transform::from_translation(-2.0 * Vect::Z), + Collider::cuboid(100.0, 1.0, 100.0), + )); + for x in 0..size { + for z in 0..size { + commands.spawn(( + RigidBody::Dynamic, + Transform::from_translation(Vec3::new(x as f32, 2.0, z as f32)), + Collider::cuboid(1.0, 1.0, 1.0), + )); + } + } + }); +} + +fn criterion_benchmark(c: &mut Criterion) { + c.bench_function("cubes 3x3, 30 steps", |b| { + bench_app(b, 30, |app| setup_cubes(app, 3)) + }); + + c.bench_function("cubes 5x5, 30 steps", |b| { + bench_app(b, 30, |app| setup_cubes(app, 5)) + }); + + c.bench_function("cubes 10x10, 30 steps", |b| { + bench_app(b, 30, |app| setup_cubes(app, 10)) + }); +} + +criterion_group!( + name = benches; + config = Criterion::default().measurement_time(Duration::from_secs(20)); + targets = criterion_benchmark +); +criterion_main!(benches); From 89186b686736c95aa643b94328e0fef8e2994af0 Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 3 Jul 2024 08:28:27 +0200 Subject: [PATCH 02/16] fix ci ? --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68cedd9a..1af7497e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,7 @@ on: env: CARGO_TERM_COLOR: always RUST_CACHE_KEY: rust-cache-20240617 + CARGO_PROFILE_DEV_DEBUG: none jobs: check-fmt: From 35c6630060f9d99745069570fdfb98e931bfbc5a Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 3 Jul 2024 12:35:22 +0200 Subject: [PATCH 03/16] use divan + try a custom bench strategy --- benches_common/Cargo.toml | 2 +- benches_common/src/lib.rs | 82 +++++++++--------- bevy_rapier3d/Cargo.toml | 14 ++- bevy_rapier3d/benches/cubes.rs | 36 ++++---- bevy_rapier3d/benches/many_pyramids3.rs | 86 +++++++++++++++++++ .../benches/many_pyramids3_custom.rs | 53 ++++++++++++ 6 files changed, 210 insertions(+), 63 deletions(-) create mode 100644 bevy_rapier3d/benches/many_pyramids3.rs create mode 100644 bevy_rapier3d/benches/many_pyramids3_custom.rs diff --git a/benches_common/Cargo.toml b/benches_common/Cargo.toml index e3068d18..4b2c1377 100644 --- a/benches_common/Cargo.toml +++ b/benches_common/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" [dependencies] bevy = { version = "0.14.0-rc.3", default-features = false } bevy_rapier3d = { path = "../bevy_rapier3d", default-features = false } -criterion = "0.5" +divan = "0.1" diff --git a/benches_common/src/lib.rs b/benches_common/src/lib.rs index 70aa35bf..9b79d6f3 100644 --- a/benches_common/src/lib.rs +++ b/benches_common/src/lib.rs @@ -9,55 +9,55 @@ use bevy::{ time::TimeUpdateStrategy, }; use bevy_rapier3d::prelude::*; -use criterion::{measurement::Measurement, BatchSize, Bencher}; -pub fn bench_app( - bencher: &mut Bencher<'_, M>, - steps: u32, - setup: impl Fn(&mut App), -) { - bencher.iter_batched_ref( - move || { - let mut app = App::new(); +pub fn default_app() -> App { + let mut app = App::new(); - app.add_plugins(( - WindowPlugin::default(), - MinimalPlugins, - AssetPlugin::default(), - ScenePlugin, - RenderPlugin { - render_creation: RenderCreation::Automatic(WgpuSettings { - backends: None, - ..Default::default() - }), - ..Default::default() - }, - ImagePlugin::default(), - HierarchyPlugin, - TransformPlugin, - RapierPhysicsPlugin::<()>::default(), - )); + app.add_plugins(( + WindowPlugin::default(), + MinimalPlugins, + AssetPlugin::default(), + ScenePlugin, + RenderPlugin { + render_creation: RenderCreation::Automatic(WgpuSettings { + backends: None, + ..Default::default() + }), + ..Default::default() + }, + ImagePlugin::default(), + HierarchyPlugin, + TransformPlugin, + RapierPhysicsPlugin::<()>::default(), + )); - // 60 physics - app.insert_resource(TimeUpdateStrategy::ManualDuration( - std::time::Duration::from_secs_f32(1f32 / 60f32), - )); + // 60 physics + app.insert_resource(TimeUpdateStrategy::ManualDuration( + std::time::Duration::from_secs_f32(1f32 / 60f32), + )); + app +} - setup(&mut app); +pub fn wait_app_start(app: &mut App) { + while app.plugins_state() != PluginsState::Ready { + bevy::tasks::tick_global_task_pools_on_main_thread(); + } - while app.plugins_state() != PluginsState::Ready { - bevy::tasks::tick_global_task_pools_on_main_thread(); - } + app.finish(); + app.cleanup(); +} - app.finish(); - app.cleanup(); +pub fn bench_app(bencher: divan::Bencher, steps: u32, setup: impl Fn(&mut App)) { + bencher + .with_inputs(|| { + let mut app = default_app(); + setup(&mut app); + wait_app_start(&mut app); app - }, - move |app| { + }) + .bench_local_values(|mut app| { for _ in 0..steps { app.update(); } - }, - BatchSize::PerIteration, - ); + }); } diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index c817f66c..d503afac 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -61,7 +61,11 @@ bevy = { version = "0.14.0-rc.3", default-features = false, features = [ ] } approx = "0.5.1" glam = { version = "0.27", features = ["approx"] } -criterion = { version = "0.5", features = ["html_reports"] } +divan = "0.1" + +[dev-dependencies.rapier3d] +features = ["profiler"] +version = "0.20" [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs @@ -70,3 +74,11 @@ features = ["debug-render-3d", "serde-serialize"] [[bench]] name = "cubes" harness = false + +[[bench]] +name = "many_pyramids3" +harness = false + +[[bench]] +name = "many_pyramids3_custom" +harness = false diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs index 0377f21d..014976a8 100644 --- a/bevy_rapier3d/benches/cubes.rs +++ b/bevy_rapier3d/benches/cubes.rs @@ -1,10 +1,9 @@ -use std::time::Duration; +//! Translated from avian benchmark. use benches_common::bench_app; use bevy::prelude::*; use bevy_rapier3d::math::*; use bevy_rapier3d::prelude::*; -use criterion::{criterion_group, criterion_main, Criterion}; fn setup_cubes(app: &mut App, size: u32) { app.add_systems(Startup, move |mut commands: Commands| { @@ -25,23 +24,20 @@ fn setup_cubes(app: &mut App, size: u32) { }); } -fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("cubes 3x3, 30 steps", |b| { - bench_app(b, 30, |app| setup_cubes(app, 3)) - }); - - c.bench_function("cubes 5x5, 30 steps", |b| { - bench_app(b, 30, |app| setup_cubes(app, 5)) - }); - - c.bench_function("cubes 10x10, 30 steps", |b| { - bench_app(b, 30, |app| setup_cubes(app, 10)) - }); +#[divan::bench] +fn cubes_3x3_30_steps(bencher: divan::Bencher) { + bench_app(bencher, 30, |app| setup_cubes(app, 3)) +} +#[divan::bench] +fn cubes_5x5_30_steps(bencher: divan::Bencher) { + bench_app(bencher, 30, |app| setup_cubes(app, 5)) +} +#[divan::bench] +fn cubes_10x10__30_steps(bencher: divan::Bencher) { + bench_app(bencher, 30, |app| setup_cubes(app, 10)) } -criterion_group!( - name = benches; - config = Criterion::default().measurement_time(Duration::from_secs(20)); - targets = criterion_benchmark -); -criterion_main!(benches); +fn main() { + // Run registered benchmarks. + divan::main(); +} diff --git a/bevy_rapier3d/benches/many_pyramids3.rs b/bevy_rapier3d/benches/many_pyramids3.rs new file mode 100644 index 00000000..7e0b1191 --- /dev/null +++ b/bevy_rapier3d/benches/many_pyramids3.rs @@ -0,0 +1,86 @@ +//! Translated from rapier benchmark. + +use benches_common::bench_app; +use bevy::prelude::*; +use bevy_rapier3d::math::*; +use bevy_rapier3d::prelude::*; + +pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { + let shift = rad * 2.0; + + for i in 0usize..stack_height { + for j in i..stack_height { + let fj = j as f32; + let fi = i as f32; + let x = (fi * shift / 2.0) + (fj - fi) * shift; + let y = fi * shift; + + // Build the rigid body. + commands.spawn(( + RigidBody::Dynamic, + Transform::from_translation(Vec3::new(x, y, 0.0) + offset), + Collider::cuboid(1.0, 1.0, 1.0), + )); + } + } +} + +pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { + app.add_systems(Startup, move |mut commands: Commands| { + let rad = 0.5; + let spacing = 4.0; + + /* + * Ground + */ + let ground_size = 50.0; + let ground_height = 0.1; + + commands.spawn(( + RigidBody::Fixed, + Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), + Collider::cuboid( + ground_size, + ground_height, + pyramid_count as f32 * spacing / 2.0 + ground_size, + ), + )); + + /* + * Create the cubes + */ + for pyramid_index in 0..pyramid_count { + let bottomy = rad; + create_pyramid( + &mut commands, + Vect::new( + 0.0, + bottomy, + (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, + ), + stack_height, + rad, + ); + } + }); +} + +#[divan::bench(sample_count = 5, sample_size = 5)] +fn pyramid_1_with_height_2(bencher: divan::Bencher) { + bench_app(bencher, 1000, |app| setup_cubes(app, 1, 2)); +} + +#[divan::bench(sample_count = 2, sample_size = 2)] +fn pyramid_1_with_height_20(bencher: divan::Bencher) { + bench_app(bencher, 100, |app| setup_cubes(app, 1, 20)); +} + +#[divan::bench(sample_count = 1, sample_size = 1)] +fn pyramid_2_with_height_20(bencher: divan::Bencher) { + bench_app(bencher, 100, |app| setup_cubes(app, 2, 20)); +} + +fn main() { + // Run registered benchmarks. + divan::main(); +} diff --git a/bevy_rapier3d/benches/many_pyramids3_custom.rs b/bevy_rapier3d/benches/many_pyramids3_custom.rs new file mode 100644 index 00000000..3ad20298 --- /dev/null +++ b/bevy_rapier3d/benches/many_pyramids3_custom.rs @@ -0,0 +1,53 @@ +//! Translated from rapier benchmark. + +use benches_common::default_app; +use benches_common::wait_app_start; +use bevy::prelude::*; +use bevy_rapier3d::plugin::RapierContext; +use bevy_rapier3d::plugin::SimulationToRenderTime; +use many_pyramids3::setup_cubes; +mod many_pyramids3; + +pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { + let mut app = default_app(); + setup(&mut app); + wait_app_start(&mut app); + + let mut timer_total = rapier3d::counters::Timer::new(); + let mut timer_full_update = rapier3d::counters::Timer::new(); + let mut bevy_overheads = vec![]; + let mut rapier_step_times = vec![]; + let mut total_update_times = vec![]; + timer_total.start(); + for _ in 0..steps { + timer_full_update.start(); + app.update(); + timer_full_update.pause(); + let elapsed_time = timer_full_update.time() as f32; + let rc = app.world().resource::(); + let bevy_overhead = app.world().resource::(); + bevy_overheads.push(bevy_overhead.diff); + rapier_step_times.push(rc.pipeline.counters.step_time.time() as f32); + total_update_times.push(elapsed_time); + } + timer_total.pause(); + let average = bevy_overheads.iter().sum::() / bevy_overheads.len() as f32; + println!("average bevy overhead: {}", average); + let average = total_update_times.iter().sum::() / total_update_times.len() as f32; + println!("average total time: {}", average); + let average = rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; + println!("average rapier step time: {}", average); + println!("total time: {}", timer_total.time()); +} +fn pyramid_1_with_height_2() { + custom_bencher(1000, |app| setup_cubes(app, 1, 2)); +} + +fn pyramid_2_with_height_20() { + custom_bencher(100, |app| setup_cubes(app, 2, 20)); +} + +fn main() { + pyramid_1_with_height_2(); + pyramid_2_with_height_20(); +} From f3a3d79d6314e98e2b6c39523de9f1d0983494e0 Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 3 Jul 2024 12:48:13 +0200 Subject: [PATCH 04/16] bigger test for pyramid to have comparable performances to rapier manypyramid --- bevy_rapier3d/benches/many_pyramids3_custom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bevy_rapier3d/benches/many_pyramids3_custom.rs b/bevy_rapier3d/benches/many_pyramids3_custom.rs index 3ad20298..6fb17ac4 100644 --- a/bevy_rapier3d/benches/many_pyramids3_custom.rs +++ b/bevy_rapier3d/benches/many_pyramids3_custom.rs @@ -44,7 +44,7 @@ fn pyramid_1_with_height_2() { } fn pyramid_2_with_height_20() { - custom_bencher(100, |app| setup_cubes(app, 2, 20)); + custom_bencher(100, |app| setup_cubes(app, 3, 20)); } fn main() { From c0be019763771c8426eb956786219842d2b9d48e Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 09:59:22 +0200 Subject: [PATCH 05/16] custom benches --- Cargo.toml | 2 +- .../benches/many_pyramids3_custom.rs | 65 +++++++++- custom_benches/Cargo.toml | 58 +++++++++ custom_benches/src/main.rs | 115 ++++++++++++++++++ 4 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 custom_benches/Cargo.toml create mode 100644 custom_benches/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 69f7b7de..e231382e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["bevy_rapier2d", "bevy_rapier3d"] +members = ["bevy_rapier2d", "bevy_rapier3d", "custom_benches"] resolver = "2" [profile.dev] diff --git a/bevy_rapier3d/benches/many_pyramids3_custom.rs b/bevy_rapier3d/benches/many_pyramids3_custom.rs index 6fb17ac4..b1f42b5f 100644 --- a/bevy_rapier3d/benches/many_pyramids3_custom.rs +++ b/bevy_rapier3d/benches/many_pyramids3_custom.rs @@ -3,10 +3,71 @@ use benches_common::default_app; use benches_common::wait_app_start; use bevy::prelude::*; +use bevy_rapier3d::dynamics::RigidBody; +use bevy_rapier3d::geometry::Collider; +use bevy_rapier3d::math::Vect; use bevy_rapier3d::plugin::RapierContext; use bevy_rapier3d::plugin::SimulationToRenderTime; -use many_pyramids3::setup_cubes; -mod many_pyramids3; + +pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { + let shift = rad * 2.0; + + for i in 0usize..stack_height { + for j in i..stack_height { + let fj = j as f32; + let fi = i as f32; + let x = (fi * shift / 2.0) + (fj - fi) * shift; + let y = fi * shift; + + // Build the rigid body. + commands.spawn(( + RigidBody::Dynamic, + Transform::from_translation(Vec3::new(x, y, 0.0) + offset), + Collider::cuboid(1.0, 1.0, 1.0), + )); + } + } +} + +pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { + app.add_systems(Startup, move |mut commands: Commands| { + let rad = 0.5; + let spacing = 4.0; + + /* + * Ground + */ + let ground_size = 50.0; + let ground_height = 0.1; + + commands.spawn(( + RigidBody::Fixed, + Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), + Collider::cuboid( + ground_size, + ground_height, + pyramid_count as f32 * spacing / 2.0 + ground_size, + ), + )); + + /* + * Create the cubes + */ + for pyramid_index in 0..pyramid_count { + let bottomy = rad; + create_pyramid( + &mut commands, + Vect::new( + 0.0, + bottomy, + (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, + ), + stack_height, + rad, + ); + } + }); +} pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { let mut app = default_app(); diff --git a/custom_benches/Cargo.toml b/custom_benches/Cargo.toml new file mode 100644 index 00000000..a715fc0f --- /dev/null +++ b/custom_benches/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "custom_benches" +version = "0.27.0-rc.1" +authors = ["Sébastien Crozet "] +description = "3-dimensional physics engine in Rust, official Bevy plugin." +documentation = "http://docs.rs/bevy_rapier3d" +homepage = "http://rapier.rs" +repository = "https://github.com/dimforge/bevy_rapier" +readme = "../README.md" +keywords = ["physics", "dynamics", "rigid", "real-time", "joints"] +license = "Apache-2.0" +edition = "2021" + + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +path = "../src/lib.rs" +required-features = ["dim3"] + +[features] +default = ["dim3", "async-collider", "debug-render-3d"] +dim3 = [] +debug-render = ["debug-render-3d"] +debug-render-2d = [ + "bevy/bevy_core_pipeline", + "bevy/bevy_sprite", + "bevy/bevy_gizmos", + "rapier3d/debug-render", + "bevy/bevy_asset", +] +debug-render-3d = [ + "bevy/bevy_core_pipeline", + "bevy/bevy_pbr", + "bevy/bevy_gizmos", + "rapier3d/debug-render", + "bevy/bevy_asset", +] +parallel = ["rapier3d/parallel"] +simd-stable = ["rapier3d/simd-stable"] +simd-nightly = ["rapier3d/simd-nightly"] +wasm-bindgen = ["rapier3d/wasm-bindgen"] +serde-serialize = ["rapier3d/serde-serialize", "bevy/serialize", "serde"] +enhanced-determinism = ["rapier3d/enhanced-determinism"] +headless = [] +async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"] + +[dependencies] +rapier3d = { features = ["profiler"], version = "0.20" } +bevy_rapier3d = { path = "../bevy_rapier3d" } +bevy = { version = "0.14.0-rc.3", default-features = false } +nalgebra = { version = "0.32.6", features = ["convert-glam027"] } +bitflags = "2.4" +log = "0.4" +serde = { version = "1", features = ["derive"], optional = true } +benches_common = { path = "../benches_common" } + +[profile.release] +debug = true diff --git a/custom_benches/src/main.rs b/custom_benches/src/main.rs new file mode 100644 index 00000000..ee151de3 --- /dev/null +++ b/custom_benches/src/main.rs @@ -0,0 +1,115 @@ +//! Translated from rapier benchmark. +//! +use benches_common::default_app; +use benches_common::wait_app_start; +use bevy::prelude::*; +use bevy_rapier3d::dynamics::RigidBody; +use bevy_rapier3d::geometry::Collider; +use bevy_rapier3d::math::Vect; +use bevy_rapier3d::plugin::RapierContext; +use bevy_rapier3d::plugin::SimulationToRenderTime; + +pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { + let shift = rad * 2.0; + + for i in 0usize..stack_height { + for j in i..stack_height { + let fj = j as f32; + let fi = i as f32; + let x = (fi * shift / 2.0) + (fj - fi) * shift; + let y = fi * shift; + + // Build the rigid body. + commands.spawn(( + RigidBody::Dynamic, + Transform::from_translation(Vec3::new(x, y, 0.0) + offset), + Collider::cuboid(1.0, 1.0, 1.0), + )); + } + } +} + +pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { + app.add_systems(Startup, move |mut commands: Commands| { + let rad = 0.5; + let spacing = 4.0; + + /* + * Ground + */ + let ground_size = 50.0; + let ground_height = 0.1; + + commands.spawn(( + RigidBody::Fixed, + Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), + Collider::cuboid( + ground_size, + ground_height, + pyramid_count as f32 * spacing / 2.0 + ground_size, + ), + )); + + /* + * Create the cubes + */ + for pyramid_index in 0..pyramid_count { + let bottomy = rad; + create_pyramid( + &mut commands, + Vect::new( + 0.0, + bottomy, + (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, + ), + stack_height, + rad, + ); + } + }); +} + +pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { + let mut app = default_app(); + setup(&mut app); + wait_app_start(&mut app); + + let mut timer_total = rapier3d::counters::Timer::new(); + let mut timer_full_update = rapier3d::counters::Timer::new(); + let mut bevy_overheads = vec![]; + let mut rapier_step_times = vec![]; + let mut total_update_times = vec![]; + timer_total.start(); + for _ in 0..steps { + timer_full_update.start(); + app.update(); + timer_full_update.pause(); + let elapsed_time = timer_full_update.time() as f32; + let rc = app.world().resource::(); + let bevy_overhead = app.world().resource::(); + bevy_overheads.push(bevy_overhead.diff); + rapier_step_times.push(rc.pipeline.counters.step_time.time() as f32); + total_update_times.push(elapsed_time); + } + timer_total.pause(); + let average = bevy_overheads.iter().sum::() / bevy_overheads.len() as f32; + println!("average bevy overhead: {}", average); + let average = total_update_times.iter().sum::() / total_update_times.len() as f32; + println!("average total time: {}", average); + let average = rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; + println!("average rapier step time: {}", average); + println!("total time: {}", timer_total.time()); +} + +fn pyramid_1_with_height_2() { + custom_bencher(1000, |app| setup_cubes(app, 1, 2)); +} + +fn pyramid_2_with_height_20() { + custom_bencher(100, |app| setup_cubes(app, 3, 20)); +} + +fn main() { + pyramid_1_with_height_2(); + pyramid_2_with_height_20(); +} From 64e2e1e11e842e1e38a36e6df17314d53ecc725d Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 11:06:02 +0200 Subject: [PATCH 06/16] cleanup duplicate test; add a readme for benches --- bevy_rapier3d/Cargo.toml | 8 -- .../benches/many_pyramids3_custom.rs | 114 ------------------ custom_benches/Cargo.toml | 8 +- custom_benches/README.md | 20 +++ custom_benches/src/main.rs | 17 ++- 5 files changed, 31 insertions(+), 136 deletions(-) delete mode 100644 bevy_rapier3d/benches/many_pyramids3_custom.rs create mode 100644 custom_benches/README.md diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index 14d3d7a3..ac314c8d 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -63,10 +63,6 @@ approx = "0.5.1" glam = { version = "0.27", features = ["approx"] } divan = "0.1" -[dev-dependencies.rapier3d] -features = ["profiler"] -version = "0.20" - [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs features = ["debug-render-3d", "serde-serialize"] @@ -78,7 +74,3 @@ harness = false [[bench]] name = "many_pyramids3" harness = false - -[[bench]] -name = "many_pyramids3_custom" -harness = false diff --git a/bevy_rapier3d/benches/many_pyramids3_custom.rs b/bevy_rapier3d/benches/many_pyramids3_custom.rs deleted file mode 100644 index b1f42b5f..00000000 --- a/bevy_rapier3d/benches/many_pyramids3_custom.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Translated from rapier benchmark. - -use benches_common::default_app; -use benches_common::wait_app_start; -use bevy::prelude::*; -use bevy_rapier3d::dynamics::RigidBody; -use bevy_rapier3d::geometry::Collider; -use bevy_rapier3d::math::Vect; -use bevy_rapier3d::plugin::RapierContext; -use bevy_rapier3d::plugin::SimulationToRenderTime; - -pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { - let shift = rad * 2.0; - - for i in 0usize..stack_height { - for j in i..stack_height { - let fj = j as f32; - let fi = i as f32; - let x = (fi * shift / 2.0) + (fj - fi) * shift; - let y = fi * shift; - - // Build the rigid body. - commands.spawn(( - RigidBody::Dynamic, - Transform::from_translation(Vec3::new(x, y, 0.0) + offset), - Collider::cuboid(1.0, 1.0, 1.0), - )); - } - } -} - -pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { - app.add_systems(Startup, move |mut commands: Commands| { - let rad = 0.5; - let spacing = 4.0; - - /* - * Ground - */ - let ground_size = 50.0; - let ground_height = 0.1; - - commands.spawn(( - RigidBody::Fixed, - Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), - Collider::cuboid( - ground_size, - ground_height, - pyramid_count as f32 * spacing / 2.0 + ground_size, - ), - )); - - /* - * Create the cubes - */ - for pyramid_index in 0..pyramid_count { - let bottomy = rad; - create_pyramid( - &mut commands, - Vect::new( - 0.0, - bottomy, - (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, - ), - stack_height, - rad, - ); - } - }); -} - -pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { - let mut app = default_app(); - setup(&mut app); - wait_app_start(&mut app); - - let mut timer_total = rapier3d::counters::Timer::new(); - let mut timer_full_update = rapier3d::counters::Timer::new(); - let mut bevy_overheads = vec![]; - let mut rapier_step_times = vec![]; - let mut total_update_times = vec![]; - timer_total.start(); - for _ in 0..steps { - timer_full_update.start(); - app.update(); - timer_full_update.pause(); - let elapsed_time = timer_full_update.time() as f32; - let rc = app.world().resource::(); - let bevy_overhead = app.world().resource::(); - bevy_overheads.push(bevy_overhead.diff); - rapier_step_times.push(rc.pipeline.counters.step_time.time() as f32); - total_update_times.push(elapsed_time); - } - timer_total.pause(); - let average = bevy_overheads.iter().sum::() / bevy_overheads.len() as f32; - println!("average bevy overhead: {}", average); - let average = total_update_times.iter().sum::() / total_update_times.len() as f32; - println!("average total time: {}", average); - let average = rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; - println!("average rapier step time: {}", average); - println!("total time: {}", timer_total.time()); -} -fn pyramid_1_with_height_2() { - custom_bencher(1000, |app| setup_cubes(app, 1, 2)); -} - -fn pyramid_2_with_height_20() { - custom_bencher(100, |app| setup_cubes(app, 3, 20)); -} - -fn main() { - pyramid_1_with_height_2(); - pyramid_2_with_height_20(); -} diff --git a/custom_benches/Cargo.toml b/custom_benches/Cargo.toml index a715fc0f..1a4c6974 100644 --- a/custom_benches/Cargo.toml +++ b/custom_benches/Cargo.toml @@ -45,14 +45,14 @@ headless = [] async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"] [dependencies] -rapier3d = { features = ["profiler"], version = "0.20" } +rapier3d = { features = ["profiler"], version = "0.21" } bevy_rapier3d = { path = "../bevy_rapier3d" } bevy = { version = "0.14.0-rc.3", default-features = false } -nalgebra = { version = "0.32.6", features = ["convert-glam027"] } +nalgebra = { version = "0.33", features = ["convert-glam027"] } bitflags = "2.4" log = "0.4" serde = { version = "1", features = ["derive"], optional = true } benches_common = { path = "../benches_common" } -[profile.release] -debug = true +[dev-dependencies] +approx = "0.5.1" diff --git a/custom_benches/README.md b/custom_benches/README.md new file mode 100644 index 00000000..91f62bd0 --- /dev/null +++ b/custom_benches/README.md @@ -0,0 +1,20 @@ + +## cargo bench + +within `bevy_rapier3d`: + +```sh +cargo bench +``` + +## Custom benches + +```sh +cargo run --release -p custom_benches +``` + +## Flamegraph + +```sh +CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph +``` diff --git a/custom_benches/src/main.rs b/custom_benches/src/main.rs index ee151de3..641d80cc 100644 --- a/custom_benches/src/main.rs +++ b/custom_benches/src/main.rs @@ -7,7 +7,6 @@ use bevy_rapier3d::dynamics::RigidBody; use bevy_rapier3d::geometry::Collider; use bevy_rapier3d::math::Vect; use bevy_rapier3d::plugin::RapierContext; -use bevy_rapier3d::plugin::SimulationToRenderTime; pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { let shift = rad * 2.0; @@ -76,7 +75,6 @@ pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { let mut timer_total = rapier3d::counters::Timer::new(); let mut timer_full_update = rapier3d::counters::Timer::new(); - let mut bevy_overheads = vec![]; let mut rapier_step_times = vec![]; let mut total_update_times = vec![]; timer_total.start(); @@ -86,18 +84,17 @@ pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { timer_full_update.pause(); let elapsed_time = timer_full_update.time() as f32; let rc = app.world().resource::(); - let bevy_overhead = app.world().resource::(); - bevy_overheads.push(bevy_overhead.diff); rapier_step_times.push(rc.pipeline.counters.step_time.time() as f32); total_update_times.push(elapsed_time); } timer_total.pause(); - let average = bevy_overheads.iter().sum::() / bevy_overheads.len() as f32; - println!("average bevy overhead: {}", average); - let average = total_update_times.iter().sum::() / total_update_times.len() as f32; - println!("average total time: {}", average); - let average = rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; - println!("average rapier step time: {}", average); + let average_total = total_update_times.iter().sum::() / total_update_times.len() as f32; + println!("average total time: {}", average_total); + let average_rapier_step = + rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; + println!("average rapier step time: {}", average_rapier_step); + let average_rapier_overhead = average_total - average_rapier_step; + println!("average bevy overhead: {}", average_rapier_overhead); println!("total time: {}", timer_total.time()); } From 52b3a35fd19321b4c91ce943c05649304d7ea4fc Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 11:12:56 +0200 Subject: [PATCH 07/16] simpler cargo.toml for custom_benches --- custom_benches/Cargo.toml | 48 ++------------------------------------- 1 file changed, 2 insertions(+), 46 deletions(-) diff --git a/custom_benches/Cargo.toml b/custom_benches/Cargo.toml index 1a4c6974..6613f9f8 100644 --- a/custom_benches/Cargo.toml +++ b/custom_benches/Cargo.toml @@ -1,58 +1,14 @@ [package] name = "custom_benches" -version = "0.27.0-rc.1" -authors = ["Sébastien Crozet "] -description = "3-dimensional physics engine in Rust, official Bevy plugin." -documentation = "http://docs.rs/bevy_rapier3d" -homepage = "http://rapier.rs" -repository = "https://github.com/dimforge/bevy_rapier" -readme = "../README.md" -keywords = ["physics", "dynamics", "rigid", "real-time", "joints"] +description = "Custom benchmarks for bevy_rapier." +readme = "./README.md" license = "Apache-2.0" edition = "2021" - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[lib] -path = "../src/lib.rs" -required-features = ["dim3"] - -[features] -default = ["dim3", "async-collider", "debug-render-3d"] -dim3 = [] -debug-render = ["debug-render-3d"] -debug-render-2d = [ - "bevy/bevy_core_pipeline", - "bevy/bevy_sprite", - "bevy/bevy_gizmos", - "rapier3d/debug-render", - "bevy/bevy_asset", -] -debug-render-3d = [ - "bevy/bevy_core_pipeline", - "bevy/bevy_pbr", - "bevy/bevy_gizmos", - "rapier3d/debug-render", - "bevy/bevy_asset", -] -parallel = ["rapier3d/parallel"] -simd-stable = ["rapier3d/simd-stable"] -simd-nightly = ["rapier3d/simd-nightly"] -wasm-bindgen = ["rapier3d/wasm-bindgen"] -serde-serialize = ["rapier3d/serde-serialize", "bevy/serialize", "serde"] -enhanced-determinism = ["rapier3d/enhanced-determinism"] -headless = [] -async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"] [dependencies] rapier3d = { features = ["profiler"], version = "0.21" } bevy_rapier3d = { path = "../bevy_rapier3d" } bevy = { version = "0.14.0-rc.3", default-features = false } -nalgebra = { version = "0.33", features = ["convert-glam027"] } -bitflags = "2.4" -log = "0.4" -serde = { version = "1", features = ["derive"], optional = true } benches_common = { path = "../benches_common" } - -[dev-dependencies] -approx = "0.5.1" From 82aed44e52d4681a84729ddb37f7f4aeff7ec795 Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 11:14:39 +0200 Subject: [PATCH 08/16] licence for benches_common --- benches_common/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/benches_common/Cargo.toml b/benches_common/Cargo.toml index 4b2c1377..08ad24ab 100644 --- a/benches_common/Cargo.toml +++ b/benches_common/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "benches_common" version = "0.1.0" +license = "Apache-2.0" edition = "2021" [dependencies] From aecf7eaa6a01b4c5e06035b69954c2aaaefde45f Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 11:15:42 +0200 Subject: [PATCH 09/16] custom bench version --- custom_benches/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/custom_benches/Cargo.toml b/custom_benches/Cargo.toml index 6613f9f8..95917ba2 100644 --- a/custom_benches/Cargo.toml +++ b/custom_benches/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "custom_benches" +version = "0.1.0" description = "Custom benchmarks for bevy_rapier." readme = "./README.md" license = "Apache-2.0" From dd19b7e7b6f615d2641941b1680e326b0d05d081 Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 11:37:28 +0200 Subject: [PATCH 10/16] minor fixes --- bevy_rapier3d/benches/cubes.rs | 2 +- custom_benches/README.md | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs index 014976a8..5aea15b3 100644 --- a/bevy_rapier3d/benches/cubes.rs +++ b/bevy_rapier3d/benches/cubes.rs @@ -33,7 +33,7 @@ fn cubes_5x5_30_steps(bencher: divan::Bencher) { bench_app(bencher, 30, |app| setup_cubes(app, 5)) } #[divan::bench] -fn cubes_10x10__30_steps(bencher: divan::Bencher) { +fn cubes_10x10_30_steps(bencher: divan::Bencher) { bench_app(bencher, 30, |app| setup_cubes(app, 10)) } diff --git a/custom_benches/README.md b/custom_benches/README.md index 91f62bd0..ee1996ed 100644 --- a/custom_benches/README.md +++ b/custom_benches/README.md @@ -1,10 +1,8 @@ ## cargo bench -within `bevy_rapier3d`: - ```sh -cargo bench +cargo bench -p bevy_rapier3d ``` ## Custom benches From 775ab1f1463ddad4f0dafe22becaadc35b78fe7d Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 4 Jul 2024 12:27:46 +0200 Subject: [PATCH 11/16] please cargo deny --- benches_common/Cargo.toml | 2 +- bevy_rapier3d/Cargo.toml | 2 +- custom_benches/Cargo.toml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/benches_common/Cargo.toml b/benches_common/Cargo.toml index 08ad24ab..91be3fc9 100644 --- a/benches_common/Cargo.toml +++ b/benches_common/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" [dependencies] bevy = { version = "0.14.0-rc.3", default-features = false } -bevy_rapier3d = { path = "../bevy_rapier3d", default-features = false } +bevy_rapier3d = { version = "0.27.0-rc.1", path = "../bevy_rapier3d", default-features = false } divan = "0.1" diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index ac314c8d..50456fe6 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -53,7 +53,7 @@ log = "0.4" serde = { version = "1", features = ["derive"], optional = true } [dev-dependencies] -benches_common = { path = "../benches_common" } +benches_common = { version = "0.1", path = "../benches_common" } bevy = { version = "0.14.0-rc.3", default-features = false, features = [ "x11", "tonemapping_luts", diff --git a/custom_benches/Cargo.toml b/custom_benches/Cargo.toml index 95917ba2..e511f4fa 100644 --- a/custom_benches/Cargo.toml +++ b/custom_benches/Cargo.toml @@ -10,6 +10,6 @@ edition = "2021" [dependencies] rapier3d = { features = ["profiler"], version = "0.21" } -bevy_rapier3d = { path = "../bevy_rapier3d" } +bevy_rapier3d = { version = "0.27.0-rc.1", path = "../bevy_rapier3d" } bevy = { version = "0.14.0-rc.3", default-features = false } -benches_common = { path = "../benches_common" } +benches_common = { version = "0.1", path = "../benches_common" } From 4e6b7535cefd4aad9b6fe81ddf218601cf27fdbc Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 10 Jul 2024 09:18:18 +0200 Subject: [PATCH 12/16] added permalinks to benches --- bevy_rapier3d/benches/cubes.rs | 2 ++ bevy_rapier3d/benches/many_pyramids3.rs | 2 ++ custom_benches/src/main.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs index 5aea15b3..49008f9f 100644 --- a/bevy_rapier3d/benches/cubes.rs +++ b/bevy_rapier3d/benches/cubes.rs @@ -1,4 +1,6 @@ //! Translated from avian benchmark. +//! +//! https://github.com/Jondolf/avian/blob/81290423e146264120cf9711af716f6faf669717/crates/avian3d/benches/cubes.rs. use benches_common::bench_app; use bevy::prelude::*; diff --git a/bevy_rapier3d/benches/many_pyramids3.rs b/bevy_rapier3d/benches/many_pyramids3.rs index 7e0b1191..51994aad 100644 --- a/bevy_rapier3d/benches/many_pyramids3.rs +++ b/bevy_rapier3d/benches/many_pyramids3.rs @@ -1,4 +1,6 @@ //! Translated from rapier benchmark. +//! +//! https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs use benches_common::bench_app; use bevy::prelude::*; diff --git a/custom_benches/src/main.rs b/custom_benches/src/main.rs index 641d80cc..4ee06b16 100644 --- a/custom_benches/src/main.rs +++ b/custom_benches/src/main.rs @@ -1,5 +1,7 @@ //! Translated from rapier benchmark. //! +//! https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs + use benches_common::default_app; use benches_common::wait_app_start; use bevy::prelude::*; From 2cda62241a016c419e74537e9f60a9ccb66d7af7 Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 10 Jul 2024 11:24:33 +0200 Subject: [PATCH 13/16] divan benchmarks update timings independently --- benches_common/src/lib.rs | 21 ++++++++------------- bevy_rapier3d/benches/cubes.rs | 24 ++++++++++++++---------- bevy_rapier3d/benches/many_pyramids3.rs | 14 +++++++------- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/benches_common/src/lib.rs b/benches_common/src/lib.rs index 9b79d6f3..02471a39 100644 --- a/benches_common/src/lib.rs +++ b/benches_common/src/lib.rs @@ -47,17 +47,12 @@ pub fn wait_app_start(app: &mut App) { app.cleanup(); } -pub fn bench_app(bencher: divan::Bencher, steps: u32, setup: impl Fn(&mut App)) { - bencher - .with_inputs(|| { - let mut app = default_app(); - setup(&mut app); - wait_app_start(&mut app); - app - }) - .bench_local_values(|mut app| { - for _ in 0..steps { - app.update(); - } - }); +pub fn bench_app_updates(bencher: divan::Bencher, setup: impl Fn(&mut App)) { + let mut app = default_app(); + setup(&mut app); + wait_app_start(&mut app); + + bencher.bench_local(|| { + app.update(); + }); } diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs index 49008f9f..77f46282 100644 --- a/bevy_rapier3d/benches/cubes.rs +++ b/bevy_rapier3d/benches/cubes.rs @@ -2,7 +2,7 @@ //! //! https://github.com/Jondolf/avian/blob/81290423e146264120cf9711af716f6faf669717/crates/avian3d/benches/cubes.rs. -use benches_common::bench_app; +use benches_common::bench_app_updates; use bevy::prelude::*; use bevy_rapier3d::math::*; use bevy_rapier3d::prelude::*; @@ -26,17 +26,21 @@ fn setup_cubes(app: &mut App, size: u32) { }); } -#[divan::bench] -fn cubes_3x3_30_steps(bencher: divan::Bencher) { - bench_app(bencher, 30, |app| setup_cubes(app, 3)) +#[divan::bench(sample_count = 60, sample_size = 1)] +fn cubes_3x3(bencher: divan::Bencher) { + bench_app_updates(bencher, |app| setup_cubes(app, 3)) } -#[divan::bench] -fn cubes_5x5_30_steps(bencher: divan::Bencher) { - bench_app(bencher, 30, |app| setup_cubes(app, 5)) +#[divan::bench(sample_count = 60, sample_size = 1)] +fn cubes_5x5(bencher: divan::Bencher) { + bench_app_updates(bencher, |app| setup_cubes(app, 5)) } -#[divan::bench] -fn cubes_10x10_30_steps(bencher: divan::Bencher) { - bench_app(bencher, 30, |app| setup_cubes(app, 10)) +#[divan::bench(sample_count = 60, sample_size = 1)] +fn cubes_10x10(bencher: divan::Bencher) { + bench_app_updates(bencher, |app| setup_cubes(app, 10)) +} +#[divan::bench(sample_count = 60, sample_size = 1)] +fn cubes_20x20(bencher: divan::Bencher) { + bench_app_updates(bencher, |app| setup_cubes(app, 20)) } fn main() { diff --git a/bevy_rapier3d/benches/many_pyramids3.rs b/bevy_rapier3d/benches/many_pyramids3.rs index 51994aad..ff9199c9 100644 --- a/bevy_rapier3d/benches/many_pyramids3.rs +++ b/bevy_rapier3d/benches/many_pyramids3.rs @@ -2,7 +2,7 @@ //! //! https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs -use benches_common::bench_app; +use benches_common::bench_app_updates; use bevy::prelude::*; use bevy_rapier3d::math::*; use bevy_rapier3d::prelude::*; @@ -67,19 +67,19 @@ pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { }); } -#[divan::bench(sample_count = 5, sample_size = 5)] +#[divan::bench(sample_count = 60, sample_size = 1)] fn pyramid_1_with_height_2(bencher: divan::Bencher) { - bench_app(bencher, 1000, |app| setup_cubes(app, 1, 2)); + bench_app_updates(bencher, |app| setup_cubes(app, 1, 2)); } -#[divan::bench(sample_count = 2, sample_size = 2)] +#[divan::bench(sample_count = 60, sample_size = 1)] fn pyramid_1_with_height_20(bencher: divan::Bencher) { - bench_app(bencher, 100, |app| setup_cubes(app, 1, 20)); + bench_app_updates(bencher, |app| setup_cubes(app, 1, 20)); } -#[divan::bench(sample_count = 1, sample_size = 1)] +#[divan::bench(sample_count = 60, sample_size = 1)] fn pyramid_2_with_height_20(bencher: divan::Bencher) { - bench_app(bencher, 100, |app| setup_cubes(app, 2, 20)); + bench_app_updates(bencher, |app| setup_cubes(app, 2, 20)); } fn main() { From 74315eb485b6c74b99c46895d2f511477e4f2e5c Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Wed, 10 Jul 2024 15:29:59 +0200 Subject: [PATCH 14/16] fix cargo doc --- bevy_rapier3d/benches/cubes.rs | 2 +- bevy_rapier3d/benches/many_pyramids3.rs | 2 +- custom_benches/src/main.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs index 77f46282..99b91ca0 100644 --- a/bevy_rapier3d/benches/cubes.rs +++ b/bevy_rapier3d/benches/cubes.rs @@ -1,6 +1,6 @@ //! Translated from avian benchmark. //! -//! https://github.com/Jondolf/avian/blob/81290423e146264120cf9711af716f6faf669717/crates/avian3d/benches/cubes.rs. +//! use benches_common::bench_app_updates; use bevy::prelude::*; diff --git a/bevy_rapier3d/benches/many_pyramids3.rs b/bevy_rapier3d/benches/many_pyramids3.rs index ff9199c9..405af32e 100644 --- a/bevy_rapier3d/benches/many_pyramids3.rs +++ b/bevy_rapier3d/benches/many_pyramids3.rs @@ -1,6 +1,6 @@ //! Translated from rapier benchmark. //! -//! https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs +//! use benches_common::bench_app_updates; use bevy::prelude::*; diff --git a/custom_benches/src/main.rs b/custom_benches/src/main.rs index 4ee06b16..cbe141d1 100644 --- a/custom_benches/src/main.rs +++ b/custom_benches/src/main.rs @@ -1,6 +1,6 @@ //! Translated from rapier benchmark. //! -//! https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs +//! use benches_common::default_app; use benches_common::wait_app_start; From 3bb2b1a154c69a9619b70f63ca157fd80731020e Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Thu, 11 Jul 2024 12:03:32 +0200 Subject: [PATCH 15/16] rearrange hierarchy and readme --- Cargo.toml | 2 +- benches_common/Cargo.toml | 10 -------- bevy_rapier3d/Cargo.toml | 1 - .../benches/common/mod.rs | 0 bevy_rapier3d/benches/cubes.rs | 5 +++- bevy_rapier3d/benches/many_pyramids3.rs | 4 ++++ .../Cargo.toml | 2 +- bevy_rapier_benches3d/README.md | 24 +++++++++++++++++++ .../src/main.rs | 0 custom_benches/README.md | 18 -------------- 10 files changed, 34 insertions(+), 32 deletions(-) delete mode 100644 benches_common/Cargo.toml rename benches_common/src/lib.rs => bevy_rapier3d/benches/common/mod.rs (100%) rename {custom_benches => bevy_rapier_benches3d}/Cargo.toml (94%) create mode 100644 bevy_rapier_benches3d/README.md rename {custom_benches => bevy_rapier_benches3d}/src/main.rs (100%) delete mode 100644 custom_benches/README.md diff --git a/Cargo.toml b/Cargo.toml index e231382e..69f7b7de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["bevy_rapier2d", "bevy_rapier3d", "custom_benches"] +members = ["bevy_rapier2d", "bevy_rapier3d"] resolver = "2" [profile.dev] diff --git a/benches_common/Cargo.toml b/benches_common/Cargo.toml deleted file mode 100644 index 91be3fc9..00000000 --- a/benches_common/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "benches_common" -version = "0.1.0" -license = "Apache-2.0" -edition = "2021" - -[dependencies] -bevy = { version = "0.14.0-rc.3", default-features = false } -bevy_rapier3d = { version = "0.27.0-rc.1", path = "../bevy_rapier3d", default-features = false } -divan = "0.1" diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index 6703766d..77faff1c 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -53,7 +53,6 @@ log = "0.4" serde = { version = "1", features = ["derive"], optional = true } [dev-dependencies] -benches_common = { version = "0.1", path = "../benches_common" } bevy = { version = "0.14", default-features = false, features = [ "x11", "tonemapping_luts", diff --git a/benches_common/src/lib.rs b/bevy_rapier3d/benches/common/mod.rs similarity index 100% rename from benches_common/src/lib.rs rename to bevy_rapier3d/benches/common/mod.rs diff --git a/bevy_rapier3d/benches/cubes.rs b/bevy_rapier3d/benches/cubes.rs index 99b91ca0..6095783f 100644 --- a/bevy_rapier3d/benches/cubes.rs +++ b/bevy_rapier3d/benches/cubes.rs @@ -2,7 +2,10 @@ //! //! -use benches_common::bench_app_updates; +mod common; + +use common::bench_app_updates; + use bevy::prelude::*; use bevy_rapier3d::math::*; use bevy_rapier3d::prelude::*; diff --git a/bevy_rapier3d/benches/many_pyramids3.rs b/bevy_rapier3d/benches/many_pyramids3.rs index 405af32e..ed001d6e 100644 --- a/bevy_rapier3d/benches/many_pyramids3.rs +++ b/bevy_rapier3d/benches/many_pyramids3.rs @@ -2,6 +2,10 @@ //! //! +mod common; + +use common::bench_app_updates; + use benches_common::bench_app_updates; use bevy::prelude::*; use bevy_rapier3d::math::*; diff --git a/custom_benches/Cargo.toml b/bevy_rapier_benches3d/Cargo.toml similarity index 94% rename from custom_benches/Cargo.toml rename to bevy_rapier_benches3d/Cargo.toml index e511f4fa..b40e2ed2 100644 --- a/custom_benches/Cargo.toml +++ b/bevy_rapier_benches3d/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "custom_benches" +name = "bevy_rapier_benches3d" version = "0.1.0" description = "Custom benchmarks for bevy_rapier." readme = "./README.md" diff --git a/bevy_rapier_benches3d/README.md b/bevy_rapier_benches3d/README.md new file mode 100644 index 00000000..96271738 --- /dev/null +++ b/bevy_rapier_benches3d/README.md @@ -0,0 +1,24 @@ +# bevy_rapier custom benches + +`bevy_rapier_benches3d` 's objective is to measure timings with detailed information +without spending too much time running multiple times expensive benchmarks. + +It is implemented as a standalone binary, running different scenes setup, gathering information +and outputs them at the end. + +```sh +cargo run --release -p bevy_rapier_benches3d +``` + +## cargo bench + +For short-lived benchmarks based on statistical analysis, +benchmarks can be run through the [divan](https://github.com/nvzqz/divan) bench harness. + +```sh +cargo bench -p bevy_rapier3d +``` + +## Other resources + +- [Bevy profiling](https://github.com/bevyengine/bevy/blob/main/docs/profiling.md) diff --git a/custom_benches/src/main.rs b/bevy_rapier_benches3d/src/main.rs similarity index 100% rename from custom_benches/src/main.rs rename to bevy_rapier_benches3d/src/main.rs diff --git a/custom_benches/README.md b/custom_benches/README.md deleted file mode 100644 index ee1996ed..00000000 --- a/custom_benches/README.md +++ /dev/null @@ -1,18 +0,0 @@ - -## cargo bench - -```sh -cargo bench -p bevy_rapier3d -``` - -## Custom benches - -```sh -cargo run --release -p custom_benches -``` - -## Flamegraph - -```sh -CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -``` From 7bf425ba557e7a6d0a739e9ecd70e7309e37903a Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Fri, 12 Jul 2024 12:09:56 +0200 Subject: [PATCH 16/16] fix compilation ; removed some duplicate code --- Cargo.toml | 2 +- bevy_rapier3d/Cargo.toml | 1 + bevy_rapier3d/benches/common.rs | 12 ++ bevy_rapier3d/benches/many_pyramids3.rs | 72 +---------- bevy_rapier_benches3d/Cargo.toml | 1 - bevy_rapier_benches3d/README.md | 2 +- bevy_rapier_benches3d/src/bin/bench.rs | 14 +++ .../src/common.rs | 10 -- bevy_rapier_benches3d/src/lib.rs | 42 +++++++ bevy_rapier_benches3d/src/main.rs | 114 ------------------ bevy_rapier_benches3d/src/pyramids.rs | 64 ++++++++++ 11 files changed, 139 insertions(+), 195 deletions(-) create mode 100644 bevy_rapier3d/benches/common.rs create mode 100644 bevy_rapier_benches3d/src/bin/bench.rs rename bevy_rapier3d/benches/common/mod.rs => bevy_rapier_benches3d/src/common.rs (83%) create mode 100644 bevy_rapier_benches3d/src/lib.rs delete mode 100644 bevy_rapier_benches3d/src/main.rs create mode 100644 bevy_rapier_benches3d/src/pyramids.rs diff --git a/Cargo.toml b/Cargo.toml index 69f7b7de..01b43b09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["bevy_rapier2d", "bevy_rapier3d"] +members = ["bevy_rapier2d", "bevy_rapier3d", "bevy_rapier_benches3d"] resolver = "2" [profile.dev] diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index 77faff1c..58690f76 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -61,6 +61,7 @@ bevy = { version = "0.14", default-features = false, features = [ approx = "0.5.1" glam = { version = "0.27", features = ["approx"] } divan = "0.1" +bevy_rapier_benches3d = { version = "0.1", path = "../bevy_rapier_benches3d" } [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs diff --git a/bevy_rapier3d/benches/common.rs b/bevy_rapier3d/benches/common.rs new file mode 100644 index 00000000..86229fc4 --- /dev/null +++ b/bevy_rapier3d/benches/common.rs @@ -0,0 +1,12 @@ +use bevy::app::App; +use bevy_rapier_benches3d::common::{default_app, wait_app_start}; + +pub fn bench_app_updates(bencher: divan::Bencher, setup: impl Fn(&mut App)) { + let mut app = default_app(); + setup(&mut app); + wait_app_start(&mut app); + + bencher.bench_local(|| { + app.update(); + }); +} diff --git a/bevy_rapier3d/benches/many_pyramids3.rs b/bevy_rapier3d/benches/many_pyramids3.rs index ed001d6e..e4ca49a4 100644 --- a/bevy_rapier3d/benches/many_pyramids3.rs +++ b/bevy_rapier3d/benches/many_pyramids3.rs @@ -4,86 +4,22 @@ mod common; +use bevy_rapier_benches3d::pyramids::setup_pyramids; use common::bench_app_updates; -use benches_common::bench_app_updates; -use bevy::prelude::*; -use bevy_rapier3d::math::*; -use bevy_rapier3d::prelude::*; - -pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { - let shift = rad * 2.0; - - for i in 0usize..stack_height { - for j in i..stack_height { - let fj = j as f32; - let fi = i as f32; - let x = (fi * shift / 2.0) + (fj - fi) * shift; - let y = fi * shift; - - // Build the rigid body. - commands.spawn(( - RigidBody::Dynamic, - Transform::from_translation(Vec3::new(x, y, 0.0) + offset), - Collider::cuboid(1.0, 1.0, 1.0), - )); - } - } -} - -pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { - app.add_systems(Startup, move |mut commands: Commands| { - let rad = 0.5; - let spacing = 4.0; - - /* - * Ground - */ - let ground_size = 50.0; - let ground_height = 0.1; - - commands.spawn(( - RigidBody::Fixed, - Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), - Collider::cuboid( - ground_size, - ground_height, - pyramid_count as f32 * spacing / 2.0 + ground_size, - ), - )); - - /* - * Create the cubes - */ - for pyramid_index in 0..pyramid_count { - let bottomy = rad; - create_pyramid( - &mut commands, - Vect::new( - 0.0, - bottomy, - (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, - ), - stack_height, - rad, - ); - } - }); -} - #[divan::bench(sample_count = 60, sample_size = 1)] fn pyramid_1_with_height_2(bencher: divan::Bencher) { - bench_app_updates(bencher, |app| setup_cubes(app, 1, 2)); + bench_app_updates(bencher, |app| setup_pyramids(app, 1, 2)); } #[divan::bench(sample_count = 60, sample_size = 1)] fn pyramid_1_with_height_20(bencher: divan::Bencher) { - bench_app_updates(bencher, |app| setup_cubes(app, 1, 20)); + bench_app_updates(bencher, |app| setup_pyramids(app, 1, 20)); } #[divan::bench(sample_count = 60, sample_size = 1)] fn pyramid_2_with_height_20(bencher: divan::Bencher) { - bench_app_updates(bencher, |app| setup_cubes(app, 2, 20)); + bench_app_updates(bencher, |app| setup_pyramids(app, 2, 20)); } fn main() { diff --git a/bevy_rapier_benches3d/Cargo.toml b/bevy_rapier_benches3d/Cargo.toml index b40e2ed2..2bb0caba 100644 --- a/bevy_rapier_benches3d/Cargo.toml +++ b/bevy_rapier_benches3d/Cargo.toml @@ -12,4 +12,3 @@ edition = "2021" rapier3d = { features = ["profiler"], version = "0.21" } bevy_rapier3d = { version = "0.27.0-rc.1", path = "../bevy_rapier3d" } bevy = { version = "0.14.0-rc.3", default-features = false } -benches_common = { version = "0.1", path = "../benches_common" } diff --git a/bevy_rapier_benches3d/README.md b/bevy_rapier_benches3d/README.md index 96271738..7079cd61 100644 --- a/bevy_rapier_benches3d/README.md +++ b/bevy_rapier_benches3d/README.md @@ -7,7 +7,7 @@ It is implemented as a standalone binary, running different scenes setup, gather and outputs them at the end. ```sh -cargo run --release -p bevy_rapier_benches3d +cargo run --release --bin bench ``` ## cargo bench diff --git a/bevy_rapier_benches3d/src/bin/bench.rs b/bevy_rapier_benches3d/src/bin/bench.rs new file mode 100644 index 00000000..e864541b --- /dev/null +++ b/bevy_rapier_benches3d/src/bin/bench.rs @@ -0,0 +1,14 @@ +use bevy_rapier_benches3d::{custom_bencher, pyramids::setup_pyramids}; + +fn pyramid_1_with_height_2() { + custom_bencher(1000, |app| setup_pyramids(app, 1, 2)); +} + +fn pyramid_2_with_height_20() { + custom_bencher(100, |app| setup_pyramids(app, 3, 20)); +} + +fn main() { + pyramid_1_with_height_2(); + pyramid_2_with_height_20(); +} diff --git a/bevy_rapier3d/benches/common/mod.rs b/bevy_rapier_benches3d/src/common.rs similarity index 83% rename from bevy_rapier3d/benches/common/mod.rs rename to bevy_rapier_benches3d/src/common.rs index 02471a39..9a2f5f6f 100644 --- a/bevy_rapier3d/benches/common/mod.rs +++ b/bevy_rapier_benches3d/src/common.rs @@ -46,13 +46,3 @@ pub fn wait_app_start(app: &mut App) { app.finish(); app.cleanup(); } - -pub fn bench_app_updates(bencher: divan::Bencher, setup: impl Fn(&mut App)) { - let mut app = default_app(); - setup(&mut app); - wait_app_start(&mut app); - - bencher.bench_local(|| { - app.update(); - }); -} diff --git a/bevy_rapier_benches3d/src/lib.rs b/bevy_rapier_benches3d/src/lib.rs new file mode 100644 index 00000000..3e3220aa --- /dev/null +++ b/bevy_rapier_benches3d/src/lib.rs @@ -0,0 +1,42 @@ +//! Translated from rapier benchmark. +//! +//! + +pub mod common; +pub mod pyramids; + +use common::default_app; +use common::wait_app_start; + +use bevy::prelude::*; +use bevy_rapier3d::plugin::RapierContext; + +pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { + let mut app = default_app(); + setup(&mut app); + wait_app_start(&mut app); + + let mut timer_total = rapier3d::counters::Timer::new(); + let mut timer_full_update = rapier3d::counters::Timer::new(); + let mut rapier_step_times = vec![]; + let mut total_update_times = vec![]; + timer_total.start(); + for _ in 0..steps { + timer_full_update.start(); + app.update(); + timer_full_update.pause(); + let elapsed_time = timer_full_update.time() as f32; + let rc = app.world().resource::(); + rapier_step_times.push(rc.pipeline.counters.step_time.time() as f32); + total_update_times.push(elapsed_time); + } + timer_total.pause(); + let average_total = total_update_times.iter().sum::() / total_update_times.len() as f32; + println!("average total time: {} ms", average_total); + let average_rapier_step = + rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; + println!("average rapier step time: {} ms", average_rapier_step); + let average_rapier_overhead = average_total - average_rapier_step; + println!("average bevy overhead: {} ms", average_rapier_overhead); + println!("total time: {} ms", timer_total.time()); +} diff --git a/bevy_rapier_benches3d/src/main.rs b/bevy_rapier_benches3d/src/main.rs deleted file mode 100644 index cbe141d1..00000000 --- a/bevy_rapier_benches3d/src/main.rs +++ /dev/null @@ -1,114 +0,0 @@ -//! Translated from rapier benchmark. -//! -//! - -use benches_common::default_app; -use benches_common::wait_app_start; -use bevy::prelude::*; -use bevy_rapier3d::dynamics::RigidBody; -use bevy_rapier3d::geometry::Collider; -use bevy_rapier3d::math::Vect; -use bevy_rapier3d::plugin::RapierContext; - -pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { - let shift = rad * 2.0; - - for i in 0usize..stack_height { - for j in i..stack_height { - let fj = j as f32; - let fi = i as f32; - let x = (fi * shift / 2.0) + (fj - fi) * shift; - let y = fi * shift; - - // Build the rigid body. - commands.spawn(( - RigidBody::Dynamic, - Transform::from_translation(Vec3::new(x, y, 0.0) + offset), - Collider::cuboid(1.0, 1.0, 1.0), - )); - } - } -} - -pub fn setup_cubes(app: &mut App, pyramid_count: usize, stack_height: usize) { - app.add_systems(Startup, move |mut commands: Commands| { - let rad = 0.5; - let spacing = 4.0; - - /* - * Ground - */ - let ground_size = 50.0; - let ground_height = 0.1; - - commands.spawn(( - RigidBody::Fixed, - Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), - Collider::cuboid( - ground_size, - ground_height, - pyramid_count as f32 * spacing / 2.0 + ground_size, - ), - )); - - /* - * Create the cubes - */ - for pyramid_index in 0..pyramid_count { - let bottomy = rad; - create_pyramid( - &mut commands, - Vect::new( - 0.0, - bottomy, - (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, - ), - stack_height, - rad, - ); - } - }); -} - -pub fn custom_bencher(steps: usize, setup: impl Fn(&mut App)) { - let mut app = default_app(); - setup(&mut app); - wait_app_start(&mut app); - - let mut timer_total = rapier3d::counters::Timer::new(); - let mut timer_full_update = rapier3d::counters::Timer::new(); - let mut rapier_step_times = vec![]; - let mut total_update_times = vec![]; - timer_total.start(); - for _ in 0..steps { - timer_full_update.start(); - app.update(); - timer_full_update.pause(); - let elapsed_time = timer_full_update.time() as f32; - let rc = app.world().resource::(); - rapier_step_times.push(rc.pipeline.counters.step_time.time() as f32); - total_update_times.push(elapsed_time); - } - timer_total.pause(); - let average_total = total_update_times.iter().sum::() / total_update_times.len() as f32; - println!("average total time: {}", average_total); - let average_rapier_step = - rapier_step_times.iter().sum::() / rapier_step_times.len() as f32; - println!("average rapier step time: {}", average_rapier_step); - let average_rapier_overhead = average_total - average_rapier_step; - println!("average bevy overhead: {}", average_rapier_overhead); - println!("total time: {}", timer_total.time()); -} - -fn pyramid_1_with_height_2() { - custom_bencher(1000, |app| setup_cubes(app, 1, 2)); -} - -fn pyramid_2_with_height_20() { - custom_bencher(100, |app| setup_cubes(app, 3, 20)); -} - -fn main() { - pyramid_1_with_height_2(); - pyramid_2_with_height_20(); -} diff --git a/bevy_rapier_benches3d/src/pyramids.rs b/bevy_rapier_benches3d/src/pyramids.rs new file mode 100644 index 00000000..363538a9 --- /dev/null +++ b/bevy_rapier_benches3d/src/pyramids.rs @@ -0,0 +1,64 @@ +use bevy::prelude::*; +use bevy_rapier3d::dynamics::RigidBody; +use bevy_rapier3d::geometry::Collider; +use bevy_rapier3d::math::Vect; + +pub fn create_pyramid(commands: &mut Commands, offset: Vect, stack_height: usize, rad: f32) { + let shift = rad * 2.0; + + for i in 0usize..stack_height { + for j in i..stack_height { + let fj = j as f32; + let fi = i as f32; + let x = (fi * shift / 2.0) + (fj - fi) * shift; + let y = fi * shift; + + // Build the rigid body. + commands.spawn(( + RigidBody::Dynamic, + Transform::from_translation(Vec3::new(x, y, 0.0) + offset), + Collider::cuboid(1.0, 1.0, 1.0), + )); + } + } +} + +pub fn setup_pyramids(app: &mut App, pyramid_count: usize, stack_height: usize) { + app.add_systems(Startup, move |mut commands: Commands| { + let rad = 0.5; + let spacing = 4.0; + + /* + * Ground + */ + let ground_size = 50.0; + let ground_height = 0.1; + + commands.spawn(( + RigidBody::Fixed, + Transform::from_translation(Vect::new(0.0, -ground_height, 0.0)), + Collider::cuboid( + ground_size, + ground_height, + pyramid_count as f32 * spacing / 2.0 + ground_size, + ), + )); + + /* + * Create the pyramids + */ + for pyramid_index in 0..pyramid_count { + let bottomy = rad; + create_pyramid( + &mut commands, + Vect::new( + 0.0, + bottomy, + (pyramid_index as f32 - pyramid_count as f32 / 2.0) * spacing, + ), + stack_height, + rad, + ); + } + }); +}