Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down Expand Up @@ -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"
Expand Down
62 changes: 62 additions & 0 deletions benches/benches/bevy_ecs/schedule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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 sys() {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use non-empty systems here with somewhat diverse data access patterns here. One of the more important optimizations in this area of code is to immediately optimize-away edges between systems with compatible data accesses.

These systems will all be compatible, and so there's no way to spot that.

Hmm, maybe this is a good choice for another dimension to split on?

Copy link
Contributor

@hymm hymm Jun 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to add data conflicts or we'll start testing the scheduler too, instead of just the initialization.

We could maybe add a single threaded stage and add the systems to that. That would probably give the most consistent results. I guess in this scenario adding data conflicts wouldn't matter, since they're just run in topological order.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah fair. I could go either way on the single-threaded stage; my personal feeling is that this is good to merge.


// 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(sys);
}
app.run();
});
});

// Benchmark with constraints.
group.bench_function(format!("{graph_size}_schedule"), |bencher| {
bencher.iter(|| {
let mut app = App::new();
app.add_system(sys.label(DummyLabel));
for i in 0..graph_size {
let mut sys = sys.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);
}
app.run();
});
});
}

group.finish();
}