Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
Ygen
rust source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
mrustc (master)
rustc 1.0.0
rustc 1.1.0
rustc 1.10.0
rustc 1.11.0
rustc 1.12.0
rustc 1.13.0
rustc 1.14.0
rustc 1.15.1
rustc 1.16.0
rustc 1.17.0
rustc 1.18.0
rustc 1.19.0
rustc 1.2.0
rustc 1.20.0
rustc 1.21.0
rustc 1.22.0
rustc 1.23.0
rustc 1.24.0
rustc 1.25.0
rustc 1.26.0
rustc 1.27.0
rustc 1.27.1
rustc 1.28.0
rustc 1.29.0
rustc 1.3.0
rustc 1.30.0
rustc 1.31.0
rustc 1.32.0
rustc 1.33.0
rustc 1.34.0
rustc 1.35.0
rustc 1.36.0
rustc 1.37.0
rustc 1.38.0
rustc 1.39.0
rustc 1.4.0
rustc 1.40.0
rustc 1.41.0
rustc 1.42.0
rustc 1.43.0
rustc 1.44.0
rustc 1.45.0
rustc 1.45.2
rustc 1.46.0
rustc 1.47.0
rustc 1.48.0
rustc 1.49.0
rustc 1.5.0
rustc 1.50.0
rustc 1.51.0
rustc 1.52.0
rustc 1.53.0
rustc 1.54.0
rustc 1.55.0
rustc 1.56.0
rustc 1.57.0
rustc 1.58.0
rustc 1.59.0
rustc 1.6.0
rustc 1.60.0
rustc 1.61.0
rustc 1.62.0
rustc 1.63.0
rustc 1.64.0
rustc 1.65.0
rustc 1.66.0
rustc 1.67.0
rustc 1.68.0
rustc 1.69.0
rustc 1.7.0
rustc 1.70.0
rustc 1.71.0
rustc 1.72.0
rustc 1.73.0
rustc 1.74.0
rustc 1.75.0
rustc 1.76.0
rustc 1.77.0
rustc 1.78.0
rustc 1.79.0
rustc 1.8.0
rustc 1.80.0
rustc 1.81.0
rustc 1.82.0
rustc 1.9.0
rustc beta
rustc nightly
rustc-cg-gcc (master)
x86-64 GCCRS (GCC master)
x86-64 GCCRS (GCCRS master)
x86-64 GCCRS 14.1 (GCC)
x86-64 GCCRS 14.2 (GCC)
Options
Source code
use std::hash::{BuildHasher, Hasher, Hash}; use std::collections::HashSet; #[no_mangle] pub fn demo_hash(e: &Entity) -> u64 { let bh = EntityHash; bh.hash_one(e) } #[no_mangle] pub fn demo_contains(e: &Entity, set: &HashSet<Entity, EntityHash>) -> bool { set.contains(e) } /// A [`BuildHasher`] that results in a [`EntityHasher`]. #[derive(Default)] pub struct EntityHash; impl BuildHasher for EntityHash { type Hasher = EntityHasher; fn build_hasher(&self) -> Self::Hasher { EntityHasher::default() } } /// A very fast hash that is only designed to work on generational indices /// like `Entity`. It will panic if attempting to hash a type containing /// non-u64 fields. /// /// This is heavily optimized for typical cases, where you have mostly live /// entities, and works particularly well for contiguous indices. /// /// If you have an unusual case -- say all your indices are multiples of 256 /// or most of the entities are dead generations -- then you might want also to /// try [`AHasher`] for a slower hash computation but fewer lookup conflicts. #[derive(Debug, Default)] pub struct EntityHasher { hash: u64, } impl Hasher for EntityHasher { #[inline] fn write(&mut self, _bytes: &[u8]) { panic!("can only hash u64 using EntityHasher"); } #[inline] fn write_u64(&mut self, bits: u64) { // SwissTable (and thus `hashbrown`) cares about two things from the hash: // - H1: low bits (masked by `2ⁿ-1`) to pick the slot in which to store the item // - H2: high 7 bits are used to SIMD optimize hash collision probing // For more see <https://abseil.io/about/design/swisstables#metadata-layout> // This hash function assumes that the entity ids are still well-distributed, // so for H1 leaves the entity id alone in the low bits so that id locality // will also give memory locality for things spawned together. // For H2, take advantage of the fact that while multiplication doesn't // spread entropy to the low bits, it's incredibly good at spreading it // upward, which is exactly where we need it the most. // While this does include the generation in the output, it doesn't do so // *usefully*. H1 won't care until you have over 3 billion entities in // the table, and H2 won't care until something hits generation 33 million. // Thus the comment suggesting that this is best for live entities, // where there won't be generation conflicts where it would matter. // The high 32 bits of this are ⅟φ for Fibonacci hashing. That works // particularly well for hashing for the same reason as described in // <https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/> // It loses no information because it has a modular inverse. // (Specifically, `0x144c_bc89_u32 * 0x9e37_79b9_u32 == 1`.) // // The low 32 bits make that part of the just product a pass-through. const UPPER_PHI: u64 = 0x9e37_79b9_0000_0001; // This is `(MAGIC * index + generation) << 32 + index`, in a single instruction. self.hash = bits.wrapping_mul(UPPER_PHI); } #[inline] fn finish(&self) -> u64 { self.hash } } /// Lightweight identifier of an [entity](crate::entity). /// /// The identifier is implemented using a [generational index]: a combination of an index and a generation. /// This allows fast insertion after data removal in an array while minimizing loss of spatial locality. /// /// These identifiers are only valid on the [`World`] it's sourced from. Attempting to use an `Entity` to /// fetch entity components or metadata from a different world will either fail or return unexpected results. /// /// [generational index]: https://lucassardois.medium.com/generational-indices-guide-8e3c5f7fd594 /// /// # Usage /// /// This data type is returned by iterating a `Query` that has `Entity` as part of its query fetch type parameter ([learn more]). /// It can also be obtained by calling [`EntityCommands::id`] or [`EntityWorldMut::id`]. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] /// # struct SomeComponent; /// fn setup(mut commands: Commands) { /// // Calling `spawn` returns `EntityCommands`. /// let entity = commands.spawn(SomeComponent).id(); /// } /// /// fn exclusive_system(world: &mut World) { /// // Calling `spawn` returns `EntityWorldMut`. /// let entity = world.spawn(SomeComponent).id(); /// } /// # /// # bevy_ecs::system::assert_is_system(setup); /// # bevy_ecs::system::assert_is_system(exclusive_system); /// ``` /// /// It can be used to refer to a specific entity to apply [`EntityCommands`], or to call [`Query::get`] (or similar methods) to access its components. /// /// ``` /// # use bevy_ecs::prelude::*; /// # /// # #[derive(Component)] /// # struct Expired; /// # /// fn dispose_expired_food(mut commands: Commands, query: Query<Entity, With<Expired>>) { /// for food_entity in &query { /// commands.entity(food_entity).despawn(); /// } /// } /// # /// # bevy_ecs::system::assert_is_system(dispose_expired_food); /// ``` /// /// [learn more]: crate::system::Query#entity-id-access /// [`EntityCommands::id`]: crate::system::EntityCommands::id /// [`EntityWorldMut::id`]: crate::world::EntityWorldMut::id /// [`EntityCommands`]: crate::system::EntityCommands /// [`Query::get`]: crate::system::Query::get /// [`World`]: crate::world::World #[derive(Clone, Copy)] // Alignment repr necessary to allow LLVM to better output // optimised codegen for `to_bits`, `PartialEq` and `Ord`. #[repr(C, align(8))] pub struct Entity { // Do not reorder the fields here. The ordering is explicitly used by repr(C) // to make this struct equivalent to a u64. #[cfg(target_endian = "little")] index: u32, generation: u32, #[cfg(target_endian = "big")] index: u32, } // By not short-circuiting in comparisons, we get better codegen. // See <https://github.com/rust-lang/rust/issues/117800> impl PartialEq for Entity { #[inline] fn eq(&self, other: &Entity) -> bool { // By using `to_bits`, the codegen can be optimised out even // further potentially. Relies on the correct alignment/field // order of `Entity`. self.to_bits() == other.to_bits() } } impl Eq for Entity {} // The derive macro codegen output is not optimal and can't be optimised as well // by the compiler. This impl resolves the issue of non-optimal codegen by relying // on comparing against the bit representation of `Entity` instead of comparing // the fields. The result is then LLVM is able to optimise the codegen for Entity // far beyond what the derive macro can. // See <https://github.com/rust-lang/rust/issues/106107> impl PartialOrd for Entity { #[inline] fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { // Make use of our `Ord` impl to ensure optimal codegen output Some(self.cmp(other)) } } // The derive macro codegen output is not optimal and can't be optimised as well // by the compiler. This impl resolves the issue of non-optimal codegen by relying // on comparing against the bit representation of `Entity` instead of comparing // the fields. The result is then LLVM is able to optimise the codegen for Entity // far beyond what the derive macro can. // See <https://github.com/rust-lang/rust/issues/106107> impl Ord for Entity { #[inline] fn cmp(&self, other: &Self) -> std::cmp::Ordering { // This will result in better codegen for ordering comparisons, plus // avoids pitfalls with regards to macro codegen relying on property // position when we want to compare against the bit representation. self.to_bits().cmp(&other.to_bits()) } } impl Hash for Entity { #[inline] fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.to_bits().hash(state); } } impl Entity { #[cfg(test)] pub(crate) const fn new(index: u32, generation: u32) -> Entity { Entity { index, generation } } /// An entity ID with a placeholder value. This may or may not correspond to an actual entity, /// and should be overwritten by a new value before being used. /// /// ## Examples /// /// Initializing a collection (e.g. `array` or `Vec`) with a known size: /// /// ```no_run /// # use bevy_ecs::prelude::*; /// // Create a new array of size 10 filled with invalid entity ids. /// let mut entities: [Entity; 10] = [Entity::PLACEHOLDER; 10]; /// /// // ... replace the entities with valid ones. /// ``` /// /// Deriving [`Reflect`](bevy_reflect::Reflect) for a component that has an `Entity` field: /// /// ```no_run /// # use bevy_ecs::{prelude::*, component::*}; /// # use bevy_reflect::Reflect; /// #[derive(Reflect, Component)] /// #[reflect(Component)] /// pub struct MyStruct { /// pub entity: Entity, /// } /// /// impl FromWorld for MyStruct { /// fn from_world(_world: &mut World) -> Self { /// Self { /// entity: Entity::PLACEHOLDER, /// } /// } /// } /// ``` pub const PLACEHOLDER: Self = Self::from_raw(u32::MAX); /// Creates a new entity ID with the specified `index` and a generation of 0. /// /// # Note /// /// Spawning a specific `entity` value is __rarely the right choice__. Most apps should favor /// [`Commands::spawn`](crate::system::Commands::spawn). This method should generally /// only be used for sharing entities across apps, and only when they have a scheme /// worked out to share an index space (which doesn't happen by default). /// /// In general, one should not try to synchronize the ECS by attempting to ensure that /// `Entity` lines up between instances, but instead insert a secondary identifier as /// a component. pub const fn from_raw(index: u32) -> Entity { Entity { index, generation: 0, } } /// Convert to a form convenient for passing outside of rust. /// /// Only useful for identifying entities within the same instance of an application. Do not use /// for serialization between runs. /// /// No particular structure is guaranteed for the returned bits. pub const fn to_bits(self) -> u64 { (self.generation as u64) << 32 | self.index as u64 } }
rust source #2
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
mrustc (master)
rustc 1.0.0
rustc 1.1.0
rustc 1.10.0
rustc 1.11.0
rustc 1.12.0
rustc 1.13.0
rustc 1.14.0
rustc 1.15.1
rustc 1.16.0
rustc 1.17.0
rustc 1.18.0
rustc 1.19.0
rustc 1.2.0
rustc 1.20.0
rustc 1.21.0
rustc 1.22.0
rustc 1.23.0
rustc 1.24.0
rustc 1.25.0
rustc 1.26.0
rustc 1.27.0
rustc 1.27.1
rustc 1.28.0
rustc 1.29.0
rustc 1.3.0
rustc 1.30.0
rustc 1.31.0
rustc 1.32.0
rustc 1.33.0
rustc 1.34.0
rustc 1.35.0
rustc 1.36.0
rustc 1.37.0
rustc 1.38.0
rustc 1.39.0
rustc 1.4.0
rustc 1.40.0
rustc 1.41.0
rustc 1.42.0
rustc 1.43.0
rustc 1.44.0
rustc 1.45.0
rustc 1.45.2
rustc 1.46.0
rustc 1.47.0
rustc 1.48.0
rustc 1.49.0
rustc 1.5.0
rustc 1.50.0
rustc 1.51.0
rustc 1.52.0
rustc 1.53.0
rustc 1.54.0
rustc 1.55.0
rustc 1.56.0
rustc 1.57.0
rustc 1.58.0
rustc 1.59.0
rustc 1.6.0
rustc 1.60.0
rustc 1.61.0
rustc 1.62.0
rustc 1.63.0
rustc 1.64.0
rustc 1.65.0
rustc 1.66.0
rustc 1.67.0
rustc 1.68.0
rustc 1.69.0
rustc 1.7.0
rustc 1.70.0
rustc 1.71.0
rustc 1.72.0
rustc 1.73.0
rustc 1.74.0
rustc 1.75.0
rustc 1.76.0
rustc 1.77.0
rustc 1.78.0
rustc 1.79.0
rustc 1.8.0
rustc 1.80.0
rustc 1.81.0
rustc 1.82.0
rustc 1.9.0
rustc beta
rustc nightly
rustc-cg-gcc (master)
x86-64 GCCRS (GCC master)
x86-64 GCCRS (GCCRS master)
x86-64 GCCRS 14.1 (GCC)
x86-64 GCCRS 14.2 (GCC)
Options
Source code
use std::hash::{BuildHasher, Hasher, Hash}; use std::collections::HashSet; #[no_mangle] pub fn demo_hash(e: &Entity) -> u64 { let bh = EntityHash; bh.hash_one(e) } #[no_mangle] pub fn demo_contains(e: &Entity, set: &HashSet<Entity, EntityHash>) -> bool { set.contains(e) } /// A [`BuildHasher`] that results in a [`EntityHasher`]. #[derive(Default)] pub struct EntityHash; impl BuildHasher for EntityHash { type Hasher = EntityHasher; fn build_hasher(&self) -> Self::Hasher { EntityHasher::default() } } /// A very fast hash that is only designed to work on generational indices /// like `Entity`. It will panic if attempting to hash a type containing /// non-u64 fields. /// /// This is heavily optimized for typical cases, where there are lots of runs /// of contiguous indices and almost no generation conflicts. /// /// If you have an unusual case -- say all your indices are multiples of 256 /// or most of the entities are dead generations -- then you might want also to /// try [`AHasher`] for a slower hash computation but fewer lookup conflicts. #[derive(Default)] pub struct EntityHasher { hash: u64, } impl Hasher for EntityHasher { #[inline] fn write(&mut self, _bytes: &[u8]) { panic!("can only hash u64 using EntityHasher"); } #[inline] fn write_u64(&mut self, i: u64) { // This value comes from rustc-hash (also known as FxHasher) which in turn got // it from Firefox. It is something like `u64::MAX / N` for an N that gives a // value close to π and works well for distributing bits for hashing when using // with a wrapping multiplication. const FRAC_U64MAX_PI: u64 = 0x517cc1b727220a95; // Apparently hashbrown's hashmap uses the upper 7 bits for some SIMD // optimisation that uses those bits for binning. This hash function // was faster than i | (i << (64 - 7)) in the worst cases, and was // faster than PassHasher for all cases tested. self.hash = i | (i.wrapping_mul(FRAC_U64MAX_PI) << 32); } #[inline] fn finish(&self) -> u64 { self.hash } } /// Lightweight identifier of an [entity](crate::entity). /// /// The identifier is implemented using a [generational index]: a combination of an index and a generation. /// This allows fast insertion after data removal in an array while minimizing loss of spatial locality. /// /// These identifiers are only valid on the [`World`] it's sourced from. Attempting to use an `Entity` to /// fetch entity components or metadata from a different world will either fail or return unexpected results. /// /// [generational index]: https://lucassardois.medium.com/generational-indices-guide-8e3c5f7fd594 /// /// # Usage /// /// This data type is returned by iterating a `Query` that has `Entity` as part of its query fetch type parameter ([learn more]). /// It can also be obtained by calling [`EntityCommands::id`] or [`EntityWorldMut::id`]. /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] /// # struct SomeComponent; /// fn setup(mut commands: Commands) { /// // Calling `spawn` returns `EntityCommands`. /// let entity = commands.spawn(SomeComponent).id(); /// } /// /// fn exclusive_system(world: &mut World) { /// // Calling `spawn` returns `EntityWorldMut`. /// let entity = world.spawn(SomeComponent).id(); /// } /// # /// # bevy_ecs::system::assert_is_system(setup); /// # bevy_ecs::system::assert_is_system(exclusive_system); /// ``` /// /// It can be used to refer to a specific entity to apply [`EntityCommands`], or to call [`Query::get`] (or similar methods) to access its components. /// /// ``` /// # use bevy_ecs::prelude::*; /// # /// # #[derive(Component)] /// # struct Expired; /// # /// fn dispose_expired_food(mut commands: Commands, query: Query<Entity, With<Expired>>) { /// for food_entity in &query { /// commands.entity(food_entity).despawn(); /// } /// } /// # /// # bevy_ecs::system::assert_is_system(dispose_expired_food); /// ``` /// /// [learn more]: crate::system::Query#entity-id-access /// [`EntityCommands::id`]: crate::system::EntityCommands::id /// [`EntityWorldMut::id`]: crate::world::EntityWorldMut::id /// [`EntityCommands`]: crate::system::EntityCommands /// [`Query::get`]: crate::system::Query::get /// [`World`]: crate::world::World #[derive(Clone, Copy)] // Alignment repr necessary to allow LLVM to better output // optimised codegen for `to_bits`, `PartialEq` and `Ord`. #[repr(C, align(8))] pub struct Entity { // Do not reorder the fields here. The ordering is explicitly used by repr(C) // to make this struct equivalent to a u64. #[cfg(target_endian = "little")] index: u32, generation: u32, #[cfg(target_endian = "big")] index: u32, } // By not short-circuiting in comparisons, we get better codegen. // See <https://github.com/rust-lang/rust/issues/117800> impl PartialEq for Entity { #[inline] fn eq(&self, other: &Entity) -> bool { // By using `to_bits`, the codegen can be optimised out even // further potentially. Relies on the correct alignment/field // order of `Entity`. self.to_bits() == other.to_bits() } } impl Eq for Entity {} // The derive macro codegen output is not optimal and can't be optimised as well // by the compiler. This impl resolves the issue of non-optimal codegen by relying // on comparing against the bit representation of `Entity` instead of comparing // the fields. The result is then LLVM is able to optimise the codegen for Entity // far beyond what the derive macro can. // See <https://github.com/rust-lang/rust/issues/106107> impl PartialOrd for Entity { #[inline] fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { // Make use of our `Ord` impl to ensure optimal codegen output Some(self.cmp(other)) } } // The derive macro codegen output is not optimal and can't be optimised as well // by the compiler. This impl resolves the issue of non-optimal codegen by relying // on comparing against the bit representation of `Entity` instead of comparing // the fields. The result is then LLVM is able to optimise the codegen for Entity // far beyond what the derive macro can. // See <https://github.com/rust-lang/rust/issues/106107> impl Ord for Entity { #[inline] fn cmp(&self, other: &Self) -> std::cmp::Ordering { // This will result in better codegen for ordering comparisons, plus // avoids pitfalls with regards to macro codegen relying on property // position when we want to compare against the bit representation. self.to_bits().cmp(&other.to_bits()) } } impl Hash for Entity { #[inline] fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.to_bits().hash(state); } } impl Entity { #[cfg(test)] pub(crate) const fn new(index: u32, generation: u32) -> Entity { Entity { index, generation } } /// An entity ID with a placeholder value. This may or may not correspond to an actual entity, /// and should be overwritten by a new value before being used. /// /// ## Examples /// /// Initializing a collection (e.g. `array` or `Vec`) with a known size: /// /// ```no_run /// # use bevy_ecs::prelude::*; /// // Create a new array of size 10 filled with invalid entity ids. /// let mut entities: [Entity; 10] = [Entity::PLACEHOLDER; 10]; /// /// // ... replace the entities with valid ones. /// ``` /// /// Deriving [`Reflect`](bevy_reflect::Reflect) for a component that has an `Entity` field: /// /// ```no_run /// # use bevy_ecs::{prelude::*, component::*}; /// # use bevy_reflect::Reflect; /// #[derive(Reflect, Component)] /// #[reflect(Component)] /// pub struct MyStruct { /// pub entity: Entity, /// } /// /// impl FromWorld for MyStruct { /// fn from_world(_world: &mut World) -> Self { /// Self { /// entity: Entity::PLACEHOLDER, /// } /// } /// } /// ``` pub const PLACEHOLDER: Self = Self::from_raw(u32::MAX); /// Creates a new entity ID with the specified `index` and a generation of 0. /// /// # Note /// /// Spawning a specific `entity` value is __rarely the right choice__. Most apps should favor /// [`Commands::spawn`](crate::system::Commands::spawn). This method should generally /// only be used for sharing entities across apps, and only when they have a scheme /// worked out to share an index space (which doesn't happen by default). /// /// In general, one should not try to synchronize the ECS by attempting to ensure that /// `Entity` lines up between instances, but instead insert a secondary identifier as /// a component. pub const fn from_raw(index: u32) -> Entity { Entity { index, generation: 0, } } /// Convert to a form convenient for passing outside of rust. /// /// Only useful for identifying entities within the same instance of an application. Do not use /// for serialization between runs. /// /// No particular structure is guaranteed for the returned bits. pub const fn to_bits(self) -> u64 { (self.generation as u64) << 32 | self.index as u64 } }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree