Skip to content

Commit

Permalink
added initial benchmarks, similar to bevy_xpbd (#551)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrixyz authored Jul 18, 2024
1 parent d190a1c commit 188dcc2
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["bevy_rapier2d", "bevy_rapier3d"]
members = ["bevy_rapier2d", "bevy_rapier3d", "bevy_rapier_benches3d"]
resolver = "2"

[profile.dev]
Expand Down
10 changes: 10 additions & 0 deletions bevy_rapier3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,17 @@ 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
features = ["debug-render-3d", "serde-serialize"]

[[bench]]
name = "cubes"
harness = false

[[bench]]
name = "many_pyramids3"
harness = false
12 changes: 12 additions & 0 deletions bevy_rapier3d/benches/common.rs
Original file line number Diff line number Diff line change
@@ -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();
});
}
52 changes: 52 additions & 0 deletions bevy_rapier3d/benches/cubes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! Translated from avian benchmark.
//!
//! <https://github.com/Jondolf/avian/blob/81290423e146264120cf9711af716f6faf669717/crates/avian3d/benches/cubes.rs>

mod common;

use common::bench_app_updates;

use bevy::prelude::*;
use bevy_rapier3d::math::*;
use bevy_rapier3d::prelude::*;

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),
));
}
}
});
}

#[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(sample_count = 60, sample_size = 1)]
fn cubes_5x5(bencher: divan::Bencher) {
bench_app_updates(bencher, |app| setup_cubes(app, 5))
}
#[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() {
// Run registered benchmarks.
divan::main();
}
28 changes: 28 additions & 0 deletions bevy_rapier3d/benches/many_pyramids3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! Translated from rapier benchmark.
//!
//! <https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs>

mod common;

use bevy_rapier_benches3d::pyramids::setup_pyramids;
use common::bench_app_updates;

#[divan::bench(sample_count = 60, sample_size = 1)]
fn pyramid_1_with_height_2(bencher: divan::Bencher) {
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_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_pyramids(app, 2, 20));
}

fn main() {
// Run registered benchmarks.
divan::main();
}
14 changes: 14 additions & 0 deletions bevy_rapier_benches3d/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "bevy_rapier_benches3d"
version = "0.1.0"
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

[dependencies]
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 }
24 changes: 24 additions & 0 deletions bevy_rapier_benches3d/README.md
Original file line number Diff line number Diff line change
@@ -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 --bin bench
```

## 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)
14 changes: 14 additions & 0 deletions bevy_rapier_benches3d/src/bin/bench.rs
Original file line number Diff line number Diff line change
@@ -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();
}
48 changes: 48 additions & 0 deletions bevy_rapier_benches3d/src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use bevy::{
app::PluginsState,
prelude::*,
render::{
settings::{RenderCreation, WgpuSettings},
RenderPlugin,
},
scene::ScenePlugin,
time::TimeUpdateStrategy,
};
use bevy_rapier3d::prelude::*;

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(),
));

// 60 physics
app.insert_resource(TimeUpdateStrategy::ManualDuration(
std::time::Duration::from_secs_f32(1f32 / 60f32),
));
app
}

pub fn wait_app_start(app: &mut App) {
while app.plugins_state() != PluginsState::Ready {
bevy::tasks::tick_global_task_pools_on_main_thread();
}

app.finish();
app.cleanup();
}
42 changes: 42 additions & 0 deletions bevy_rapier_benches3d/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//! Translated from rapier benchmark.
//!
//! <https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs>

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::<RapierContext>();
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::<f32>() / total_update_times.len() as f32;
println!("average total time: {} ms", average_total);
let average_rapier_step =
rapier_step_times.iter().sum::<f32>() / 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());
}
64 changes: 64 additions & 0 deletions bevy_rapier_benches3d/src/pyramids.rs
Original file line number Diff line number Diff line change
@@ -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,
);
}
});
}

0 comments on commit 188dcc2

Please sign in to comment.