Skip to content

Conversation

brianreavis
Copy link
Contributor

Objective

The extraction systems for materials, meshes, and skins previously iterated over RemovedComponents<ViewVisibility> in addition to more specific variants like RemovedComponents<MeshMaterial3d<M>>. This caused each system to loop through and check many irrelevant despawned entities—sometimes multiple times. With many material types, this overhead added up and became noticeable in frames with many despawns.

Screenshot 2025-02-21 at 10 28 01 AM

Solution

This PR removes superfluous RemovedComponents iteration for ViewVisibility and GlobalTransform, ensuring that we only iterate over the most specific RemovedComponents relevant to the system (e.g., material components, mesh components). This is guaranteed to match what the system originally collected.

Before (red) / After (yellow):

Screenshot 2025-02-21 at 10 46 17 AM Log plot to highlight the long tail that this PR is addressing.

@IceSentry IceSentry requested a review from pcwalton February 21, 2025 19:45
@IceSentry IceSentry added A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Feb 21, 2025
@pcwalton
Copy link
Contributor

The reason for iterating over ViewVisibility is that removing the ViewVisibility component should essentially disable an object. This is admittedly a rather surprising behavior, but I believe it matches what Bevy has traditionally done regarding "required components".

@brianreavis
Copy link
Contributor Author

brianreavis commented Feb 21, 2025

The reason for iterating over ViewVisibility is that removing the ViewVisibility component should essentially disable an object.

Isn't it impossible to remove ViewVisibility for a mesh given it's a required component for meshes? Though maybe I'm not totally following and you're saying it is technically possible (and that's a quirk of required components). Are there any cases where bevy does use that surprising behavior?

components.rs

#[derive(Component, ...)]
#[require(Transform, Visibility, VisibilityClass)]
pub struct Mesh3d(pub Handle<Mesh>);

visibility.rs

#[derive(Component, ...)]
#[require(InheritedVisibility, ViewVisibility)]
pub enum Visibility { ... }

@brianreavis
Copy link
Contributor Author

I don't think this should be blocked by #18514 or other solutions for these reasons:

  1. The worst-case scenario is that we retain the EntityAssetId<M> mapping until the entity is despawned or made visible and then hidden. It's not going to cause unexpected rendering or extra work.
  2. Removal of ViewVisibility / GlobalTransform components is a real edge case.
  3. The optimization here can demonstrably shave nearly a millisecond off the sensitive ExtractSchedule in heavy-despawn frames.

@brianreavis brianreavis force-pushed the pr-mat-mesh-skin-extract-optimization branch from 7f0f2ca to 5f9ca02 Compare April 12, 2025 22:26
@atlv24
Copy link
Contributor

atlv24 commented Jul 8, 2025

Unfortunately I do think this should be blocked on required component invariant enforcement. This is a win but at the price of a behavioral regression that will probably affect some users

@atlv24 atlv24 modified the milestones: 0.17, 0.18 Jul 8, 2025
@brianreavis
Copy link
Contributor Author

This won't cause a behavioral change because the worst case scenario is that ViewVisibility is removed and the instance simply remains in the RenderMaterial2dInstances, RenderMaterialInstances, etc hashmaps until despawn.

Copy link
Contributor

@superdump superdump left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me. I am trusting that this has no negative side effects other than the potential memory leak if those entities are not despawned. But I kind of expect we have a number of cases of that in the render world, just that they haven’t been significant enough for someone to do something about them yet.

@superdump superdump added this pull request to the merge queue Jul 9, 2025
Merged via the queue into bevyengine:main with commit d40c5b5 Jul 9, 2025
32 checks passed
@github-project-automation github-project-automation bot moved this to Done in Rendering Jul 9, 2025
@james7132 james7132 modified the milestones: 0.18, 0.17 Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times S-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

6 participants