use bevy_utils::HashMap for better performance. TypeId is predefined … (#7642)
…u64, so hash safety is not a concern
# Objective
- While reading the code, just noticed the BundleInfo's HashMap is std::collections::HashMap, which uses a slow but safe hasher.
## Solution
- Use bevy_utils::HashMap instead
benchmark diff (I run several times in a linux box, the perf improvement is consistent, though numbers varies from time to time, I paste my last run result here):
``` bash
cargo bench -- spawn
Compiling bevy_ecs v0.9.0 (/home/lishuo/developer/pr/bevy/crates/bevy_ecs)
Compiling bevy_app v0.9.0 (/home/lishuo/developer/pr/bevy/crates/bevy_app)
Compiling benches v0.1.0 (/home/lishuo/developer/pr/bevy/benches)
Finished bench [optimized] target(s) in 1m 17s
Running benches/bevy_ecs/change_detection.rs (/home/lishuo/developer/pr/bevy/benches/target/release/deps/change_detection-86c5445d0dc34529)
Gnuplot not found, using plotters backend
Running benches/bevy_ecs/benches.rs (/home/lishuo/developer/pr/bevy/benches/target/release/deps/ecs-e49b3abe80bfd8c0)
Gnuplot not found, using plotters backend
spawn_commands/2000_entities
time: [153.94 µs 159.19 µs 164.37 µs]
change: [-14.706% -11.050% -6.9633%] (p = 0.00 < 0.05)
Performance has improved.
spawn_commands/4000_entities
time: [328.77 µs 339.11 µs 349.11 µs]
change: [-7.6331% -3.9932% +0.0487%] (p = 0.06 > 0.05)
No change in performance detected.
spawn_commands/6000_entities
time: [445.01 µs 461.29 µs 477.36 µs]
change: [-16.639% -13.358% -10.006%] (p = 0.00 < 0.05)
Performance has improved.
spawn_commands/8000_entities
time: [657.94 µs 677.71 µs 696.95 µs]
change: [-8.8708% -5.2591% -1.6847%] (p = 0.01 < 0.05)
Performance has improved.
get_or_spawn/individual time: [452.02 µs 466.70 µs 482.07 µs]
change: [-17.218% -14.041% -10.728%] (p = 0.00 < 0.05)
Performance has improved.
get_or_spawn/batched time: [291.12 µs 301.12 µs 311.31 µs]
change: [-12.281% -8.9163% -5.3660%] (p = 0.00 < 0.05)
Performance has improved.
spawn_world/1_entities time: [81.668 ns 84.284 ns 86.860 ns]
change: [-12.251% -6.7872% -1.5402%] (p = 0.02 < 0.05)
Performance has improved.
spawn_world/10_entities time: [789.78 ns 821.96 ns 851.95 ns]
change: [-19.738% -14.186% -8.0733%] (p = 0.00 < 0.05)
Performance has improved.
spawn_world/100_entities
time: [7.9906 µs 8.2449 µs 8.5013 µs]
change: [-12.417% -6.6837% -0.8766%] (p = 0.02 < 0.05)
Change within noise threshold.
spawn_world/1000_entities
time: [81.602 µs 84.161 µs 86.833 µs]
change: [-13.656% -8.6520% -3.0491%] (p = 0.00 < 0.05)
Performance has improved.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
Benchmarking spawn_world/10000_entities: Warming up for 500.00 ms
Warning: Unable to complete 100 samples in 4.0s. You may wish to increase target time to 4.0s, enable flat sampling, or reduce sample count to 70.
spawn_world/10000_entities
time: [813.02 µs 839.76 µs 865.41 µs]
change: [-12.133% -6.1970% -0.2302%] (p = 0.05 < 0.05)
Change within noise threshold.
```
---
## Changelog
> This section is optional. If this was a trivial fix, or has no externally-visible impact, you can delete this section.
- use bevy_utils::HashMap for Bundles::bundle_ids
## Migration Guide
> This section is optional. If there are no breaking changes, you can delete this section.
- Not a breaking change, hashmap is internal impl.
This commit is contained in:
parent
0bce78439b
commit
11a7ff2645
@ -24,7 +24,7 @@ async-channel = "1.4"
|
|||||||
event-listener = "2.5"
|
event-listener = "2.5"
|
||||||
thread_local = "1.1.4"
|
thread_local = "1.1.4"
|
||||||
fixedbitset = "0.4.2"
|
fixedbitset = "0.4.2"
|
||||||
fxhash = "0.2"
|
rustc-hash = "1.1"
|
||||||
downcast-rs = "1.2"
|
downcast-rs = "1.2"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,6 @@ use crate::{
|
|||||||
storage::{ImmutableSparseSet, SparseArray, SparseSet, SparseSetIndex, TableId, TableRow},
|
storage::{ImmutableSparseSet, SparseArray, SparseSet, SparseSetIndex, TableId, TableRow},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
ops::{Index, IndexMut},
|
ops::{Index, IndexMut},
|
||||||
};
|
};
|
||||||
@ -601,7 +600,7 @@ impl SparseSetIndex for ArchetypeComponentId {
|
|||||||
pub struct Archetypes {
|
pub struct Archetypes {
|
||||||
pub(crate) archetypes: Vec<Archetype>,
|
pub(crate) archetypes: Vec<Archetype>,
|
||||||
pub(crate) archetype_component_count: usize,
|
pub(crate) archetype_component_count: usize,
|
||||||
archetype_ids: HashMap<ArchetypeIdentity, ArchetypeId>,
|
archetype_ids: bevy_utils::HashMap<ArchetypeIdentity, ArchetypeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Archetypes {
|
impl Archetypes {
|
||||||
|
|||||||
@ -12,10 +12,11 @@ use crate::{
|
|||||||
component::{Component, ComponentId, ComponentStorage, Components, StorageType, Tick},
|
component::{Component, ComponentId, ComponentStorage, Components, StorageType, Tick},
|
||||||
entity::{Entities, Entity, EntityLocation},
|
entity::{Entities, Entity, EntityLocation},
|
||||||
storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
|
storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
|
||||||
|
TypeIdMap,
|
||||||
};
|
};
|
||||||
use bevy_ecs_macros::all_tuples;
|
use bevy_ecs_macros::all_tuples;
|
||||||
use bevy_ptr::OwningPtr;
|
use bevy_ptr::OwningPtr;
|
||||||
use std::{any::TypeId, collections::HashMap};
|
use std::any::TypeId;
|
||||||
|
|
||||||
/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
|
/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
|
||||||
///
|
///
|
||||||
@ -683,7 +684,7 @@ impl<'a, 'b> BundleSpawner<'a, 'b> {
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Bundles {
|
pub struct Bundles {
|
||||||
bundle_infos: Vec<BundleInfo>,
|
bundle_infos: Vec<BundleInfo>,
|
||||||
bundle_ids: HashMap<TypeId, BundleId>,
|
bundle_ids: TypeIdMap<BundleId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bundles {
|
impl Bundles {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use crate::{
|
|||||||
storage::{SparseSetIndex, Storages},
|
storage::{SparseSetIndex, Storages},
|
||||||
system::{Local, Resource},
|
system::{Local, Resource},
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
|
TypeIdMap,
|
||||||
};
|
};
|
||||||
pub use bevy_ecs_macros::Component;
|
pub use bevy_ecs_macros::Component;
|
||||||
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
||||||
@ -400,8 +401,8 @@ impl ComponentDescriptor {
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Components {
|
pub struct Components {
|
||||||
components: Vec<ComponentInfo>,
|
components: Vec<ComponentInfo>,
|
||||||
indices: std::collections::HashMap<TypeId, usize, fxhash::FxBuildHasher>,
|
indices: TypeIdMap<usize>,
|
||||||
resource_indices: std::collections::HashMap<TypeId, usize, fxhash::FxBuildHasher>,
|
resource_indices: TypeIdMap<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Components {
|
impl Components {
|
||||||
|
|||||||
@ -19,6 +19,8 @@ pub mod storage;
|
|||||||
pub mod system;
|
pub mod system;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
|
use std::any::TypeId;
|
||||||
|
|
||||||
pub use bevy_ptr as ptr;
|
pub use bevy_ptr as ptr;
|
||||||
|
|
||||||
/// Most commonly used re-exported types.
|
/// Most commonly used re-exported types.
|
||||||
@ -52,6 +54,9 @@ pub mod prelude {
|
|||||||
|
|
||||||
pub use bevy_ecs_macros::all_tuples;
|
pub use bevy_ecs_macros::all_tuples;
|
||||||
|
|
||||||
|
/// A specialized hashmap type with Key of `TypeId`
|
||||||
|
type TypeIdMap<V> = rustc_hash::FxHashMap<TypeId, V>;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate as bevy_ecs;
|
use crate as bevy_ecs;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user