Add benchmarks for schedule dependency resolution (#4961)
# Objective - Add benchmarks to test the performance of `Schedule`'s system dependency resolution. ## Solution - Do a series of benchmarks while increasing the number of systems in the schedule to see how the run-time scales. - Split the benchmarks into a group with no dependencies, and a group with many dependencies.
This commit is contained in:
parent
218b0fd3b6
commit
92ea730362
@ -11,6 +11,7 @@ glam = "0.20"
|
||||
rand = "0.8"
|
||||
rand_chacha = "0.3"
|
||||
criterion = { version = "0.3", features = ["html_reports"] }
|
||||
bevy_app = { path = "../crates/bevy_app" }
|
||||
bevy_ecs = { path = "../crates/bevy_ecs" }
|
||||
bevy_reflect = { path = "../crates/bevy_reflect" }
|
||||
bevy_tasks = { path = "../crates/bevy_tasks" }
|
||||
@ -46,6 +47,11 @@ name = "world_get"
|
||||
path = "benches/bevy_ecs/world_get.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "schedule"
|
||||
path = "benches/bevy_ecs/schedule.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "reflect_list"
|
||||
path = "benches/bevy_reflect/list.rs"
|
||||
|
||||
69
benches/benches/bevy_ecs/schedule.rs
Normal file
69
benches/benches/bevy_ecs/schedule.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use bevy_app::App;
|
||||
use bevy_ecs::prelude::*;
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
criterion_group!(benches, build_schedule);
|
||||
criterion_main!(benches);
|
||||
|
||||
fn build_schedule(criterion: &mut Criterion) {
|
||||
// empty system
|
||||
fn empty_system() {}
|
||||
|
||||
// Use multiple different kinds of label to ensure that dynamic dispatch
|
||||
// doesn't somehow get optimized away.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)]
|
||||
struct NumLabel(usize);
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)]
|
||||
struct DummyLabel;
|
||||
|
||||
let mut group = criterion.benchmark_group("build_schedule");
|
||||
group.warm_up_time(std::time::Duration::from_millis(500));
|
||||
group.measurement_time(std::time::Duration::from_secs(15));
|
||||
|
||||
// Method: generate a set of `graph_size` systems which have a One True Ordering.
|
||||
// Add system to the stage with full constraints. Hopefully this should be maximimally
|
||||
// difficult for bevy to figure out.
|
||||
let labels: Vec<_> = (0..1000).map(NumLabel).collect();
|
||||
|
||||
// Benchmark graphs of different sizes.
|
||||
for graph_size in [100, 500, 1000] {
|
||||
// Basic benchmark without constraints.
|
||||
group.bench_function(format!("{graph_size}_schedule_noconstraints"), |bencher| {
|
||||
bencher.iter(|| {
|
||||
let mut app = App::new();
|
||||
for _ in 0..graph_size {
|
||||
app.add_system(empty_system);
|
||||
}
|
||||
app.update();
|
||||
});
|
||||
});
|
||||
|
||||
// Benchmark with constraints.
|
||||
group.bench_function(format!("{graph_size}_schedule"), |bencher| {
|
||||
bencher.iter(|| {
|
||||
let mut app = App::new();
|
||||
app.add_system(empty_system.label(DummyLabel));
|
||||
|
||||
// Build a fully-connected dependency graph describing the One True Ordering.
|
||||
// Not particularly realistic but this can be refined later.
|
||||
for i in 0..graph_size {
|
||||
let mut sys = empty_system.label(labels[i]).before(DummyLabel);
|
||||
for a in 0..i {
|
||||
sys = sys.after(labels[a]);
|
||||
}
|
||||
for b in i + 1..graph_size {
|
||||
sys = sys.before(labels[b]);
|
||||
}
|
||||
app.add_system(sys);
|
||||
}
|
||||
// Run the app for a single frame.
|
||||
// This is necessary since dependency resolution does not occur until the game runs.
|
||||
// FIXME: Running the game clutters up the benchmarks, so ideally we'd be
|
||||
// able to benchmark the dependency resolution directly.
|
||||
app.update();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user