Amortize the cost of freeing entities #22658
Open
+92
−37
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Objective
The biggest drawback of #18670 was that it made freeing
Entity's back to the allocator 4x slower. That meant a 20% regression in despawn performance. This PR vastly improves the performance of the entity allocator for freeing entities.Solution
Add a local free list in pace in the main entity allocator. This is an
ArrayVeccalledquick_free. When an entity is freed, add it to thequick_free. If it is full, flush the array to the full shared allocator.Currently the array has length 64, taking 512 bytes. Since this is directly included in the already massive
Worldtype, I don't think this is an issue, and I would guess boxing it would hurt performance here. It also means that there will be at most 64 freed entities that simply can't be allocated. This reduces the worst case maximum entity count from 4,294,967,296 to 4,294,967,232 (big deal).This also adds a new
free_manyfunction that is very fast compared to doing them one by one.Testing
Showcase
Here are some rough benchmarks on my M2 MAX:
Looking at the cost of freeing 1,000 entities, this makes the new allocator exactly as fast as the pre-#18670 one, 30% faster than main. The new
free_manytakes 8.7µs to free 1,000 entities where the optimizedfreetakes29.7, so another big win there.This should make up the 20% regression to despawning. It might be even faster than pre-#18670 if we increase 64 to 128 or something, but I think that's unnecessary. This could also much improve performance for despawning scenes if we can find a way to make use of
free_many, but that's a different task.