-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ecs] Rework Entity
to use u64
#2372
[ecs] Rework Entity
to use u64
#2372
Conversation
In case anyone is curious, here is a rust playground link to see the different assembly outputs. Most notably the
Old has better asm output for (by a single instruction):
the old and new have almost identical assembly for retrieving the |
could you run the benches from https://github.com/cart/ecs_bench_suite/tree/bevy-benches before/after (hopefully they don't need updating...)? |
Hmm, has anyone tried out unsafe optimizations yet? I tried adding |
Yep, that's fair! |
impl Eq for Entity {
fn eq(&self, other: &Self) -> bool {
*(self as *const Entity as *const u64) == *(other as *const Entity as *const u64)
}
} which outputs the better assembly. If we went this path, we (should) do it for (The one that still really confuses me is the |
Hmm, it looks like using arrays gets us almost all the way there, but is arguably easier to understand than bit manipulation: https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=7c664f861a7d533cbe457cf37c7cb9a0 The only function that's different is the cmp impl, but this impl is never used in actual code, and more importantly could still be improved using unsafe: https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=2fbce7c58019f4a98bb3d81f7e638515 |
The ABI is different. For Edit: the argument pass mode is identical (as the type matches |
I agree, I think the array is a little easier to understand, however, if we can avoid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
impl looks good, I have no thoughts on the performance.
pub(crate) generation: u32, | ||
pub(crate) id: u32, | ||
} | ||
pub struct Entity(u64); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a non-doc comment here saying what scheme we use and why
/// Creates a new entity reference with a generation of 0. | ||
#[inline(always)] | ||
pub fn new(id: u32) -> Entity { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually want this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've found this useful for writing tests before.
Closing for now as we don't seem to have a strong argument for adding this extra complexity. |
Objective
Entity
is defined asstruct Entity { id: u32, gen: u32 }
however, this produces sub-optimal assembly for various operations (including:Eq
,Ord
,Copy
, andnew
)Solution
Entity(u64)
and use some bit manipulation to extract/store the id/generation numbers.