Skip to content
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

Consider compacting ComputedVisibility via bitsets #4661

Closed
james7132 opened this issue May 4, 2022 · 1 comment
Closed

Consider compacting ComputedVisibility via bitsets #4661

james7132 opened this issue May 4, 2022 · 1 comment
Labels
A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible C-Performance A change motivated by improving speed, memory usage or compile times

Comments

@james7132
Copy link
Member

james7132 commented May 4, 2022

What problem does this solve or what need does it fill?

ComputedVisibility is effectively a newtype around a bool that is recomputed every frame. This representation requires a one-byte bool value and a 8-byte change tick in ECS space. This works well right now, but 7 of the 8 bits in the bool effectively go unused. A more compact representation can lead to better cache locality.

What solution would you like?

Remove ComputedVisibility as a component, and replace it with a ComputedVisibilities resource which wraps a FixedBitset. This removes the change detection overhead and uses only one bit per entity. This compact representation uses up to 72x less memory, is much more cache friendly, and reduces the fragmented iteration costs of visibility systems. The bitset would be keyed only by Entity ID, ignoring the generation to minimize memory usage. As Entities attempts to minimize holes in entity coverage, this bitset would be relatively dense. The API for such a resource could be roughly outlined as follows:

struct ComputedVisibilites {
  entities: FixedBitset,
}

impl ComputedVisibilities {
  pub fn resize(&mut self, entities: &Entities);
  pub fn clear(&mut self);
  pub fn mark_visible(&mut self, entity: Entity);
  pub fn is_visible(&self, entity: Entity);
}

As computed visibility typically follows the pattern of a once-per-frame update system, followed by the all of the extraction systems reading it in parallel, a singular resource can be used without needing additional locking.

What alternative(s) have you considered?

#3796 changes Visibility and ComputedVisibility into ZST marker components. This removes the bool entirely, but introduces further archetype fragmentation, and makes it heavier to mark certain entities as visible or not. This alternative isn't 100% incompatible with this design, as this issue only proposes changing ComputedVisibility, though using a bitset based Visibilities resource could reduce the time spent copying initial visibility state.

@james7132 james7132 added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen C-Performance A change motivated by improving speed, memory usage or compile times labels May 4, 2022
@james7132
Copy link
Member Author

james7132 commented Jun 21, 2022

As seen with the experimentation in #4663, it does seem like this would speed up clearing the bits and improving memory locality, but the overhead of doing a bit check of every visible entity in subsequent systems potentially outweighs the benefits here.

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-Feature A new feature, making something new possible C-Performance A change motivated by improving speed, memory usage or compile times
Projects
None yet
Development

No branches or pull requests

1 participant