Skip to content

In-Place Component Initialization #20420

@james7132

Description

@james7132

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

Right now, components are inserted into the ECS by first initializing them on the stack (usually in a Bundle) and then moving the value into the space allocated within ECS storage. This extra copy isn't entirely necessary, causing entity spawning/component insertion to not be a truly zero-cost abstraction.

What solution would you like?

Ideally, space would be allocated before any initialization occurs, and a pointer to the uninitialized memory is then used to directly initialize the value. If there is support for this at the type system or language level, we may be able to get away with avoiding a major change to the user facing API. However, assuming no further support from Rust itself on this, a rough sketch of the user-facing API might look like this:

// May require generalizing over Bundles and surfacing on other similar API surfaces
impl EntityMut {
  pub fn insert_in_place<C: Component>(&mut self, init: FnOnce(&mut MaybeUninit<C>));
}

impl ThinColumn {
  pub unsafe fn initialize_in_place_unchecked(&mut self, index: usize, init: impl FnOnce(OwningPtr<'_>), ...);
}

impl BlobVec {
  pub unsafe fn initialize_in_place_unchecked<T>(&mut self, index: usize, init: impl FnOnce(OwningPtr<'_>));
}

That said I'm not all that keen on exposing the deep internals of the ECS storage by running externally provided code, as there aren't many ways to keep those spaces panic safe, as seen with #20368, but this may need to be something we live with.

What alternative(s) have you considered?

Leave it as is and pay the extra memcpy costs.

Additional context

This may require more extensive language support to make this ergonomic. See rust-lang/lang-team#336 for further discussions on this topic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-FeatureA new feature, making something new possibleC-PerformanceA change motivated by improving speed, memory usage or compile times

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions