-
Notifications
You must be signed in to change notification settings - Fork 84
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
Rewrote concurrent entity allocations to be more efficient #86
Conversation
I assume that |
aae1877
to
fbfee66
Compare
Thanks for the PR! Will try to dig into it this week.
This was actually intended behavior. The principle is that sensible results are only guaranteed for |
0544798
to
cf26e71
Compare
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.
Did a deep dive. This looks awesome, thanks! Only cosmetic issues, AFAICT.
let new_id_start = (base - cmp::min(range_end, 0)) as u32; | ||
|
||
(new_id_start, new_id_end) | ||
}; |
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.
Style nit: This would be a little more concise if Range
s were computed directly without the start/end intermediate variables. For example:
let freelist_range = range_start.max(0) as usize .. range_end.max(0) as usize;
This makes several changes: - Cuts in half the number of atomic operations to reserve an Entity, and simplifies the reservation code to no longer need a retry loop. - Adds a new `reserve_entities` method that can reserve any number of Entity IDs with a single atomic subtract. - Removed the `reserved` and `free` arrays, which consumed two u32 values for every Entity ID, and replaced them with a single `pending` Vec. `pending` only needs one slot for every freed Entity. - No longer dump huge lists of fresh IDs into the freelist when we grow. The freelist only holds explicitly freed values, and we use arithmetic to acquire new IDs. - Removes the `reserved_len()`, etc. API used to flush reserved entities. Now flush() takes a closure to initialize each entity. - Tightened the restrictions on what you are allowed to do while you have unflushed reservations. - Grow meta and pending incrementally, as values are allocated and freed, rather than in a monolithic `grow` method. This turns out to make things simpler, e.g. we need to track the end of the "reserved" range of pending anyway, and using the Vec len is handy. - Adds some unit tests.
Thanks, I applied all of your feedback. |
Great stuff! |
This makes several changes:
and simplifies the reservation code to no longer need a retry loop.
reserve_entities
method that can reserve any numberof Entity IDs with a single atomic subtract.
reserved
andfree
arrays, which consumedtwo u32 values for every Entity ID, and replaced them with a single
pending
Vec.pending
only needs one slot for every freed Entity.grow. The freelist only holds explicitly freed values, and we use
arithmetic to acquire new IDs.
reserved_len()
, etc. API used to flush reservedentities. Now flush() takes a closure to initialize each entity.
have unflushed reservations.
freed, rather than in a monolithic
grow
method. This turns outto make things simpler, e.g. we need to track the end of the
"reserved" range of pending anyway, and using the Vec len is handy.