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

[Merged by Bors] - Refactor ECS to reduce the dependency on a 1-to-1 mapping between components and real rust types #2490

Closed
wants to merge 8 commits into from

Conversation

bjorn3
Copy link
Contributor

@bjorn3 bjorn3 commented Jul 16, 2021

Objective

There is currently a 1-to-1 mapping between components and real rust types. This means that it is impossible for multiple components to be represented by the same rust type or for a component to not have a rust type at all. This means that component types can't be defined in languages other than rust like necessary for scripting or sandboxed (wasm?) plugins.

Solution

Refactor ComponentDescriptor and Bundle to remove TypeInfo. Bundle now uses ComponentId instead. ComponentDescriptor is now always created from a rust type instead of through the TypeInfo indirection. A future PR may make it possible to construct a ComponentDescriptor from it's fields without a rust type being involved.

@github-actions github-actions bot added the S-Needs-Triage This issue needs to be labelled label Jul 16, 2021
@bjorn3 bjorn3 added A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change labels Jul 16, 2021
@bjorn3
Copy link
Contributor Author

bjorn3 commented Jul 16, 2021

cc @BoxyUwU re your relationships PR.

is_send_and_sync: false,
type_id: Some(TypeId::of::<T>()),
layout: Layout::new::<T>(),
drop: Self::drop_ptr::<T>,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Making this public may help with #2486, but there are probably other places that need to be changed too for it to work.

#[inline]
pub(crate) fn get_or_insert_with(
pub(crate) unsafe fn get_or_insert_with(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This method was already de-facto unsafe. Nobody checked that the TypeId in the TypeInfo matched the type_id argument.

&mut self,
type_id: TypeId,
func: impl FnOnce() -> TypeInfo,
func: impl FnOnce() -> ComponentDescriptor,
Copy link
Member

Choose a reason for hiding this comment

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

do we know if perf is actually worse without this func param? can we just take a ComponentDescriptor always and drop the type_id arg?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ComponentDescriptor allocates a String for the type name. That is not something you want in the hot path.

Copy link
Member

Choose a reason for hiding this comment

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

ah right, the string... rip

Copy link
Member

Choose a reason for hiding this comment

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

type_name returns a &'static str though, seems like we could atleast use Cow<&'static str> here. Wouldn't be the best for custom names though :frown:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cow<'static, str> would work. The name is not frequently used, so the extra branch shouldn't hurt. I will leave that for another PR though I think.

Copy link
Member

Choose a reason for hiding this comment

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

I think personally I'd rather drop the unsafe, use a Cow and then always take a ComponentDescriptor

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ComponentDescriptor is 72 bytes with String and 80 bytes with Cow, which is relatively large. https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=93f494d4a982196b786f0f7d7f69c895

Copy link
Member

@BoxyUwU BoxyUwU Jul 20, 2021

Choose a reason for hiding this comment

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

I dont know if that actually tells us anything about the performance here though? Can we run benches or whatever and see

@alice-i-cecile alice-i-cecile removed the S-Needs-Triage This issue needs to be labelled label Jul 16, 2021
@cart cart added the S-Pre-Relicense This PR was made before Bevy added the Apache license. Cannot be merged or used for other work label Jul 23, 2021
@mockersf mockersf removed the S-Pre-Relicense This PR was made before Bevy added the Apache license. Cannot be merged or used for other work label Jul 24, 2021
Copy link
Member

@cart cart left a comment

Choose a reason for hiding this comment

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

Looks good to me. Just some nits

crates/bevy_ecs/src/bundle.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/bundle.rs Outdated Show resolved Hide resolved
@cart
Copy link
Member

cart commented Jul 28, 2021

bors r+

bors bot pushed a commit that referenced this pull request Jul 28, 2021
…ponents and real rust types (#2490)

# Objective

There is currently a 1-to-1 mapping between components and real rust types. This means that it is impossible for multiple components to be represented by the same rust type or for a component to not have a rust type at all. This means that component types can't be defined in languages other than rust like necessary for scripting or sandboxed (wasm?) plugins.

## Solution

Refactor `ComponentDescriptor` and `Bundle` to remove `TypeInfo`. `Bundle` now uses `ComponentId` instead. `ComponentDescriptor` is now always created from a rust type instead of through the `TypeInfo` indirection. A future PR may make it possible to construct a `ComponentDescriptor` from it's fields without a rust type being involved.
@bors
Copy link
Contributor

bors bot commented Jul 28, 2021

Timed out.

@BoxyUwU
Copy link
Member

BoxyUwU commented Jul 28, 2021

bors retry

bors bot pushed a commit that referenced this pull request Jul 28, 2021
…ponents and real rust types (#2490)

# Objective

There is currently a 1-to-1 mapping between components and real rust types. This means that it is impossible for multiple components to be represented by the same rust type or for a component to not have a rust type at all. This means that component types can't be defined in languages other than rust like necessary for scripting or sandboxed (wasm?) plugins.

## Solution

Refactor `ComponentDescriptor` and `Bundle` to remove `TypeInfo`. `Bundle` now uses `ComponentId` instead. `ComponentDescriptor` is now always created from a rust type instead of through the `TypeInfo` indirection. A future PR may make it possible to construct a `ComponentDescriptor` from it's fields without a rust type being involved.
@cart
Copy link
Member

cart commented Jul 28, 2021

nice that worked!

@bors bors bot changed the title Refactor ECS to reduce the dependency on a 1-to-1 mapping between components and real rust types [Merged by Bors] - Refactor ECS to reduce the dependency on a 1-to-1 mapping between components and real rust types Jul 28, 2021
@bors bors bot closed this Jul 28, 2021
@bjorn3 bjorn3 deleted the ecs_improvements branch July 28, 2021 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants