Skip to content

Commit 38f190e

Browse files
committed
Tests & Benches
No functional changes in this commit.
1 parent 2a036b6 commit 38f190e

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

benches/Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,8 @@ harness = false
6161
name = "bezier"
6262
path = "benches/bevy_math/bezier.rs"
6363
harness = false
64+
65+
[[bench]]
66+
name = "utils"
67+
path = "benches/bevy_utils/entity_hash.rs"
68+
harness = false
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use bevy_ecs::entity::Entity;
2+
use bevy_utils::EntityHashSet;
3+
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
4+
use rand::{Rng, SeedableRng};
5+
use rand_chacha::ChaCha8Rng;
6+
7+
criterion_group!(benches, entity_set_build_and_lookup,);
8+
criterion_main!(benches);
9+
10+
const SIZES: [usize; 5] = [100, 316, 1000, 3162, 10000];
11+
12+
fn make_entity(rng: &mut impl Rng, size: usize) -> Entity {
13+
// -log₂(1-x) gives an exponential distribution with median 1.0
14+
// That lets us get values that are mostly small, but some are quite large
15+
// * For ids, half are in [0, size), half are unboundedly larger.
16+
// * For generations, half are in [0, 2), half are unboundedly larger.
17+
18+
let x: f64 = rng.gen();
19+
let id = -(1.0 - x).log2() * (size as f64);
20+
let x: f64 = rng.gen();
21+
let gen = -(1.0 - x).log2() * 2.0;
22+
23+
// this is not reliable, but we're internal so a hack is ok
24+
let bits = ((gen as u64) << 32) | (id as u64);
25+
let e = Entity::from_bits(bits);
26+
assert_eq!(e.index(), id as u32);
27+
assert_eq!(e.generation(), gen as u32);
28+
e
29+
}
30+
31+
fn entity_set_build_and_lookup(c: &mut Criterion) {
32+
let mut group = c.benchmark_group("entity_hash");
33+
for size in SIZES {
34+
// Get some random-but-consistent entities to use for all the benches below.
35+
let mut rng = ChaCha8Rng::seed_from_u64(size as u64);
36+
let entities = Vec::from_iter(
37+
std::iter::repeat_with(|| make_entity(&mut rng, size)).take(size),
38+
);
39+
40+
group.throughput(Throughput::Elements(size as u64));
41+
group.bench_function(
42+
BenchmarkId::new("entity_set_build", size),
43+
|bencher| {
44+
bencher.iter_with_large_drop(|| EntityHashSet::from_iter(entities.iter().copied()));
45+
},
46+
);
47+
group.bench_function(
48+
BenchmarkId::new("entity_set_lookup_hit", size),
49+
|bencher| {
50+
let set = EntityHashSet::from_iter(entities.iter().copied());
51+
bencher.iter(|| entities.iter().copied().filter(|e| set.contains(e)).count());
52+
},
53+
);
54+
group.bench_function(
55+
BenchmarkId::new("entity_set_lookup_miss_id", size),
56+
|bencher| {
57+
let set = EntityHashSet::from_iter(entities.iter().copied());
58+
bencher.iter(|| entities.iter()
59+
.copied()
60+
.map(|e| Entity::from_bits(e.to_bits() + 1))
61+
.filter(|e| set.contains(e)).count());
62+
},
63+
);
64+
group.bench_function(
65+
BenchmarkId::new("entity_set_lookup_miss_gen", size),
66+
|bencher| {
67+
let set = EntityHashSet::from_iter(entities.iter().copied());
68+
bencher.iter(|| entities.iter()
69+
.copied()
70+
.map(|e| Entity::from_bits(e.to_bits() + (1 << 32)))
71+
.filter(|e| set.contains(e)).count());
72+
},
73+
);
74+
}
75+
}

crates/bevy_ecs/src/entity/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,12 @@ mod tests {
891891

892892
const C4: u32 = Entity::from_bits(0x00dd_00ff_0000_0000).generation();
893893
assert_eq!(0x00dd_00ff, C4);
894+
895+
// Because `Eq` is derived, constants are usable in matches,
896+
// so make sure that keeps compiling.
897+
if let Entity::PLACEHOLDER = C1 {
898+
panic!()
899+
}
894900
}
895901

896902
#[test]
@@ -917,4 +923,27 @@ mod tests {
917923
assert_eq!(next_entity.index(), entity.index());
918924
assert!(next_entity.generation > entity.generation + GENERATIONS);
919925
}
926+
927+
#[test]
928+
fn entity_comparison() {
929+
assert!(Entity::new(123, 456) == Entity::new(123, 456));
930+
assert!(Entity::new(123, 789) != Entity::new(123, 456));
931+
assert!(Entity::new(123, 456) != Entity::new(123, 789));
932+
assert!(Entity::new(123, 456) != Entity::new(456, 123));
933+
934+
// ordering is by generation then by index
935+
936+
assert!(Entity::new(123, 456) >= Entity::new(123, 456));
937+
assert!(Entity::new(123, 456) <= Entity::new(123, 456));
938+
assert!(!(Entity::new(123, 456) < Entity::new(123, 456)));
939+
assert!(!(Entity::new(123, 456) > Entity::new(123, 456)));
940+
941+
assert!(Entity::new(9, 1) < Entity::new(1, 9));
942+
assert!(Entity::new(1, 9) > Entity::new(9, 1));
943+
944+
assert!(Entity::new(1, 1) < Entity::new(2, 1));
945+
assert!(Entity::new(1, 1) <= Entity::new(2, 1));
946+
assert!(Entity::new(2, 2) > Entity::new(1, 2));
947+
assert!(Entity::new(2, 2) >= Entity::new(1, 2));
948+
}
920949
}

0 commit comments

Comments
 (0)