Skip to content

Conversation

@aevyrie
Copy link
Member

@aevyrie aevyrie commented Dec 22, 2025

Objective

  • Make visibility systems less slow.
  • Saves as much as 1.2ms of CPU time on a (GPU bound) 6.7ms frame, rendering caldera hotel.

Solution

  • Use bitflags on the existing ViewVisibility component, which already hides its internal structure as a private implementation detail. I initially added a new component to track the previous visibility, a more direct translation from the hash set to using components, but using bitflags is even faster because I can use half the memory with a single u8 instead of two bools. This also removes the need for having required components as it is just an internal state detail of the visibility component.

Testing

  • Many cubes, many foxes, caldera
  • Yellow is new, red is old.
  • Note the bimodality in the old traces, this was consistently repeatable, and seems to have something to do with EntityHashSet and EntityHashMap. Worth investigating that further, as I've seen that bimodal behavior before, and blamed it on pcores vs ecores, but I verified that is not happening.
  • Summary: caldera hotel no longer exhibits bimodal performance with a pathological mode that runs very slowly. Roughly comparing the ~90th percentile performance, the optimized code is about 1.2ms faster. This is particularly significant when you consider this is running on a device that is already hitting 150fps (GPU bound), so it only has a frame budget of 6.7ms.
  • Notably, visibility checking was the last egregiously performing set of systems in the common hot path of most bevy apps, and no longer stick out as obviously slow in a frame profile:

A high level comparison of the change in CPU time by looking at just PostUpdate between old(red) and new(yellow)

image

Before

image

After

image

caldera hotel - all entities in view

For this test, I didn't touch the camera, so all entities were in view at all times.

check_visibility

image

reset_view_visibility

image

mark_newly_hidden_entities_invisible

This is 23us slower than the "fast mode" of the existing code on main, but 180-250us faster than the weird "slow mode" on main. The new code is significantly more stable, and does not exhibit the super slow mode.

image

caldera hotel - no entities in view

For this test, I immediately rotated the camera so the hotel was not in view.

check_visibility

This is largely a wash. The old code is 2us faster, but this is likely in the realm of noise.

image

reset_view_visibility

This is a big win. The main peak is about 30us faster now, but the major win is the worst case, which is nearly 500us faster.

image

mark_newly_hidden_entities_invisible

Same story as the other caldera comparison with everything in view, this is a bit slower than the fast mode, but way faster than the slow mode on main.

image

@aevyrie
Copy link
Member Author

aevyrie commented Dec 22, 2025

This needs a comments pass - visibility comments are pretty out of date, and this makes it worse.

@aevyrie aevyrie marked this pull request as draft December 22, 2025 06:49
@aevyrie
Copy link
Member Author

aevyrie commented Dec 22, 2025

Just grokked some things about why the way the code is the way it is. Need to fix some things and trying to make it way less confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant