Fix sprite performance regression since retained render world#17078
Fix sprite performance regression since retained render world#17078alice-i-cecile merged 2 commits intobevyengine:mainfrom
Conversation
As part of the retained render world changes, ExtractedSprites moved to using a `HashMap<(Entity, MainEntity), ExtractedSprite>` for its storage. The hashing of `(Entity, MainEntity)` using `FixedHash` was the source of the regression and performs much much slower than the highly-optimized `EntityHashMap`. This change moves the render world entity into a member in `ExtractedSprite` and then uses `MainEntityHashMap` for `ExtractedSprites` storage.
|
I'm not totally sure this is correct. I don't see why it wouldn't be, but I am unfamiliar with all the ins and outs of the retained render world changes. As such, I would love if @tychedelia could review this. :) |
1147b26 to
8335a73
Compare
tychedelia
left a comment
There was a problem hiding this comment.
Thanks @superdump, this fix looks exactly right. We shouldn't ever need to key off the entity pair together. Our policy has pretty much been to make sure we key all collections to MainEntity.
FYI: The reason for the (RenderEntity, MainEntity) shenanigans in the render phase is because the RenderCommand api supports looking up components on the PhaseItem via RenderCommand::ItemQuery, which needs the render world id to function. So while our internal render code almost exclusively looks up things via a MainEntity keyed collection on RenderCommand::Param, user code may not. I believe the exception here in our own code is some UI stuff. It's a bit of a mess!
|
I added this to |
|
Very neat to see that we have a net performance gain here! |
…bevyengine#17078)" This reverts commit fd330c8.
…#17078)" (#17123) # Objective Fixes #17098 It seems that it's not totally obvious how to fix this, but that reverting might be part of the solution anyway. Let's get the repo back into a working state. ## Solution Revert the [recent optimization](#17078) that broke "many-to-one main->render world entities" for 2d. ## Testing `cargo run --example text2d` `cargo run --example sprite_slice`
…gine#17078) # Objective - Fix sprite rendering performance regression since retained render world changes - The retained render world changes moved `ExtractedSprites` from using the highly-optimised `EntityHasher` with an `Entity` to using `FixedHasher` with `(Entity, MainEntity)`. This was enough to regress framerate in bevymark by 25%. ## Solution - Move the render world entity into a member of `ExtractedSprite` and change `ExtractedSprites` to use `MainEntityHashMap` for its storage - Disable sprite picking in bevymark ## Testing M4 Max. `bevymark --waves 100 --per-wave 1000 --benchmark`. main in yellow vs PR in red: <img width="590" alt="Screenshot 2025-01-01 at 16 36 22" src="https://github.com/user-attachments/assets/1e4ed6ec-3811-4abf-8b30-336153737f89" /> 20.2% median frame time reduction. <img width="594" alt="Screenshot 2025-01-01 at 16 38 37" src="https://github.com/user-attachments/assets/157c2022-cda6-4cf2-bc63-d0bc40528cf0" /> 49.7% median extract_sprites execution time reduction. Comparing 0.14.2 yellow vs PR red: <img width="593" alt="Screenshot 2025-01-01 at 16 40 06" src="https://github.com/user-attachments/assets/abd59b6f-290a-4eb6-8835-ed110af995f3" /> ~6.1% median frame time reduction. --- ## Migration Guide - `ExtractedSprites` is now using `MainEntityHashMap` for storage, which is keyed on `MainEntity`. - The render world entity corresponding to an `ExtractedSprite` is now stored in the `render_entity` member of it.
… and use a `MainEntityHashMap` for storage in `ExtractedSprites`
…gine#17078) # Objective - Fix sprite rendering performance regression since retained render world changes - The retained render world changes moved `ExtractedSprites` from using the highly-optimised `EntityHasher` with an `Entity` to using `FixedHasher` with `(Entity, MainEntity)`. This was enough to regress framerate in bevymark by 25%. ## Solution - Move the render world entity into a member of `ExtractedSprite` and change `ExtractedSprites` to use `MainEntityHashMap` for its storage - Disable sprite picking in bevymark ## Testing M4 Max. `bevymark --waves 100 --per-wave 1000 --benchmark`. main in yellow vs PR in red: <img width="590" alt="Screenshot 2025-01-01 at 16 36 22" src="https://github.com/user-attachments/assets/1e4ed6ec-3811-4abf-8b30-336153737f89" /> 20.2% median frame time reduction. <img width="594" alt="Screenshot 2025-01-01 at 16 38 37" src="https://github.com/user-attachments/assets/157c2022-cda6-4cf2-bc63-d0bc40528cf0" /> 49.7% median extract_sprites execution time reduction. Comparing 0.14.2 yellow vs PR red: <img width="593" alt="Screenshot 2025-01-01 at 16 40 06" src="https://github.com/user-attachments/assets/abd59b6f-290a-4eb6-8835-ed110af995f3" /> ~6.1% median frame time reduction. --- ## Migration Guide - `ExtractedSprites` is now using `MainEntityHashMap` for storage, which is keyed on `MainEntity`. - The render world entity corresponding to an `ExtractedSprite` is now stored in the `render_entity` member of it.
…bevyengine#17078)" (bevyengine#17123) # Objective Fixes bevyengine#17098 It seems that it's not totally obvious how to fix this, but that reverting might be part of the solution anyway. Let's get the repo back into a working state. ## Solution Revert the [recent optimization](bevyengine#17078) that broke "many-to-one main->render world entities" for 2d. ## Testing `cargo run --example text2d` `cargo run --example sprite_slice`
Objective
ExtractedSpritesfrom using the highly-optimisedEntityHasherwith anEntityto usingFixedHasherwith(Entity, MainEntity). This was enough to regress framerate in bevymark by 25%.Solution
ExtractedSpriteand changeExtractedSpritesto useMainEntityHashMapfor its storageTesting
M4 Max.
bevymark --waves 100 --per-wave 1000 --benchmark. main in yellow vs PR in red:20.2% median frame time reduction.
49.7% median extract_sprites execution time reduction.
Comparing 0.14.2 yellow vs PR red:

~6.1% median frame time reduction.
Migration Guide
ExtractedSpritesis now usingMainEntityHashMapfor storage, which is keyed onMainEntity.ExtractedSpriteis now stored in therender_entitymember of it.