Skip to content

Commit

Permalink
Skip rehashing TypeIds (#11268)
Browse files Browse the repository at this point in the history
# Objective

`TypeId` contains a high-quality hash. Whenever a lookup based on a
`TypeId` is performed (e.g. to insert/remove components), the hash is
run through a second hash function. This is unnecessary.

## Solution

Skip re-hashing `TypeId`s.

In my
[testing](https://gist.github.com/SpecificProtagonist/4b49ad74c6b82b0aedd3b4ea35121be8),
this improves lookup performance consistently by 10%-15% (of course, the
lookup is only a small part of e.g. a bundle insertion).
  • Loading branch information
SpecificProtagonist authored Jan 13, 2024
1 parent 98b62e8 commit 69760c7
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,30 @@ pub mod prelude {
pub use bevy_utils::all_tuples;

/// A specialized hashmap type with Key of [`TypeId`]
type TypeIdMap<V> = rustc_hash::FxHashMap<TypeId, V>;
type TypeIdMap<V> =
std::collections::HashMap<TypeId, V, std::hash::BuildHasherDefault<NoOpTypeIdHasher>>;

#[doc(hidden)]
#[derive(Default)]
struct NoOpTypeIdHasher(u64);

// TypeId already contains a high-quality hash, so skip re-hashing that hash.
impl std::hash::Hasher for NoOpTypeIdHasher {
fn finish(&self) -> u64 {
self.0
}

fn write(&mut self, _bytes: &[u8]) {
// This will never be called: TypeId always just calls write_u64 once!
// This is unlikely to ever change, but as it isn't officially guaranteed,
// panicking will let us detect this as fast as possible.
unimplemented!("Hashing of std::any::TypeId changed");
}

fn write_u64(&mut self, i: u64) {
self.0 = i;
}
}

#[cfg(test)]
mod tests {
Expand Down

0 comments on commit 69760c7

Please sign in to comment.