-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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] - Simplify design for *Label
s
#4957
Conversation
I have some concerns over the design here:
|
Hmm. I suspect we will want this for editor support, but I'm not actually convinced that there's a higher memory cost to leaking the memory versus just allocating a static string at compile time.
Interesting, that's a bit surprising to me. Can you explain a bit more @infmagic2047?
I would also like to see benchmarks. This will primarily show up in complex schedule intialization. I think that adding such a benchmark is good to do regardless; I'd split this out into a seperate PR. It also might show up in compile times, so I'd check that.
100% agree. The existing names are clearer, and there's no need to increase churn. |
crates/bevy_app/src/lib.rs
Outdated
|
||
/// The names of the default [`App`] stages. | ||
/// | ||
/// The relative [`Stages`](bevy_ecs::schedule::Stage) are added by [`App::add_default_stages`]. | ||
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] | ||
#[derive(Debug, Hash, PartialEq, Eq, Clone, IntoStageLabel)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As part of these changes, we should get rid of all of the extra derives on these types.
My first impression is that we should have a blanket Debug impl, remove Hash, and keep PartialEq, Eq and Clone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to break any user code unnecessarily, and I don't see how the extra derives are hurting anyone. What if we only remove them from private definitions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely revert the SystemLabel
-> IntoSystemLabel
change; it's making this PR very tricky to review due to all of the noise. Initial impressions are positive though; I don't think there's any serious loss of functionality.
Now that I think more about it, leaking should be fine in most cases. Plugins which need runtime labels can maintain a cache of
Well, in my case it's mostly a desire to have distinguishable That said, my use case can be fulfilled by modifying the derive macro to add type name as prefix (so In fact, there is another reason for printing |
This was actually the original design I had for this before publishing the issue. It's elegant, but the problem is that then the label becomes completely opaque, and you can't even print it at all. You can store an integer and the string, but that's pointless since you can just use the We can always do string interning for editor support, but I think Alice already convinced you.
In practice I don't think there's much use for arbitrary
Makes sense. Done.
I agree that benchmarks are valuable but I don't really know how to benchmark bevy. Is someone willing to help me out on discord?
Good idea, on it. |
Also, I think the |
Seems reasonable, but make a new PR :) |
100%. Come say hi in #engine-dev and people will be able to help you out :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! To do:
- Address small nits.
- Collapse the
define_label!
macro back down to a single argument. - Add and run some quick schedule construction benchmarks (another PR is probably ideal).
As commented on Discord; I meant another PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved pending not-terrible benchmark results :) I think this is a clearer and simpler way to get the same benefits.
Benchmarks: #4961 |
The benchmarks are very promising (located here) Old labels
New Labels
% Change
|
Excellent! Those are the sort of numbers I like to see. This is a one-time cost at app-startup (until #279 lands), so it's not as critical as some of the other perf optimizations, but it's still really nice to shave down app initialization time when we can. |
Rewrite {System,Stage,*}Label to use a simpler design. *Label is now a lightweight, copy-able struct. You derive `Into*Label` on your custom labels.
Update lib.rs Update lib.rs
Rename `*Label` -> `*LabelId` Rename `Into*Label` -> `*Label`
Removed the private types `StateCallback` and `StateRunCriteriaLabel`. They were added to every single state-system, but they don't appear to be "read" anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usage of strings is slightly concerning to me, but given the derive seems to prevent any major footguns I'm okay with merging this and revisiting it when dynamic plugins are more of a concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with @TheRawMeatball.
Though, when we first came up with this I don't remember us thinking much about dynamic plugins either.
bors r+ |
# Objective - Closes #4954 - Reduce the complexity of the `{System, App, *}Label` APIs. ## Solution For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well. - Add `SystemLabelId`, a lightweight, `copy` struct. - Convert custom types into `SystemLabelId` using the trait `SystemLabel`. ## Changelog - String literals implement `SystemLabel` for now, but this should be changed with #4409 . ## Migration Guide - Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`. - `AsSystemLabel` trait has been modified. - No more output generics. - Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection. - If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended. ## Questions for later * Should we generate a `Debug` impl along with `#[derive(*Label)]`? * Should we rename `as_str()`? * Should we remove the extra derives (such as `Hash`) from builtin `*Label` types? * Should we automatically derive types like `Clone, Copy, PartialEq, Eq`? * More-ergonomic comparisons between `Label` and `LabelId`. * Move `Dyn{Eq, Hash,Clone}` somewhere else. * Some API to make interning dynamic labels easier. * Optimize string representation * Empty string for unit structs -- no debug info but faster comparisons * Don't show enum types -- same tradeoffs as asbove.
Build failed: |
bors retry |
# Objective - Closes #4954 - Reduce the complexity of the `{System, App, *}Label` APIs. ## Solution For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well. - Add `SystemLabelId`, a lightweight, `copy` struct. - Convert custom types into `SystemLabelId` using the trait `SystemLabel`. ## Changelog - String literals implement `SystemLabel` for now, but this should be changed with #4409 . ## Migration Guide - Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`. - `AsSystemLabel` trait has been modified. - No more output generics. - Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection. - If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended. ## Questions for later * Should we generate a `Debug` impl along with `#[derive(*Label)]`? * Should we rename `as_str()`? * Should we remove the extra derives (such as `Hash`) from builtin `*Label` types? * Should we automatically derive types like `Clone, Copy, PartialEq, Eq`? * More-ergonomic comparisons between `Label` and `LabelId`. * Move `Dyn{Eq, Hash,Clone}` somewhere else. * Some API to make interning dynamic labels easier. * Optimize string representation * Empty string for unit structs -- no debug info but faster comparisons * Don't show enum types -- same tradeoffs as asbove.
*Label
s*Label
s
# Objective - Closes bevyengine#4954 - Reduce the complexity of the `{System, App, *}Label` APIs. ## Solution For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well. - Add `SystemLabelId`, a lightweight, `copy` struct. - Convert custom types into `SystemLabelId` using the trait `SystemLabel`. ## Changelog - String literals implement `SystemLabel` for now, but this should be changed with bevyengine#4409 . ## Migration Guide - Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`. - `AsSystemLabel` trait has been modified. - No more output generics. - Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection. - If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended. ## Questions for later * Should we generate a `Debug` impl along with `#[derive(*Label)]`? * Should we rename `as_str()`? * Should we remove the extra derives (such as `Hash`) from builtin `*Label` types? * Should we automatically derive types like `Clone, Copy, PartialEq, Eq`? * More-ergonomic comparisons between `Label` and `LabelId`. * Move `Dyn{Eq, Hash,Clone}` somewhere else. * Some API to make interning dynamic labels easier. * Optimize string representation * Empty string for unit structs -- no debug info but faster comparisons * Don't show enum types -- same tradeoffs as asbove.
# Objective - Closes bevyengine#4954 - Reduce the complexity of the `{System, App, *}Label` APIs. ## Solution For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well. - Add `SystemLabelId`, a lightweight, `copy` struct. - Convert custom types into `SystemLabelId` using the trait `SystemLabel`. ## Changelog - String literals implement `SystemLabel` for now, but this should be changed with bevyengine#4409 . ## Migration Guide - Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`. - `AsSystemLabel` trait has been modified. - No more output generics. - Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection. - If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended. ## Questions for later * Should we generate a `Debug` impl along with `#[derive(*Label)]`? * Should we rename `as_str()`? * Should we remove the extra derives (such as `Hash`) from builtin `*Label` types? * Should we automatically derive types like `Clone, Copy, PartialEq, Eq`? * More-ergonomic comparisons between `Label` and `LabelId`. * Move `Dyn{Eq, Hash,Clone}` somewhere else. * Some API to make interning dynamic labels easier. * Optimize string representation * Empty string for unit structs -- no debug info but faster comparisons * Don't show enum types -- same tradeoffs as asbove.
# Objective - Closes bevyengine#4954 - Reduce the complexity of the `{System, App, *}Label` APIs. ## Solution For the sake of brevity I will only refer to `SystemLabel`, but everything applies to all of the other label types as well. - Add `SystemLabelId`, a lightweight, `copy` struct. - Convert custom types into `SystemLabelId` using the trait `SystemLabel`. ## Changelog - String literals implement `SystemLabel` for now, but this should be changed with bevyengine#4409 . ## Migration Guide - Any previous use of `Box<dyn SystemLabel>` should be replaced with `SystemLabelId`. - `AsSystemLabel` trait has been modified. - No more output generics. - Method `as_system_label` now returns `SystemLabelId`, removing an unnecessary level of indirection. - If you *need* a label that is determined at runtime, you can use `Box::leak`. Not recommended. ## Questions for later * Should we generate a `Debug` impl along with `#[derive(*Label)]`? * Should we rename `as_str()`? * Should we remove the extra derives (such as `Hash`) from builtin `*Label` types? * Should we automatically derive types like `Clone, Copy, PartialEq, Eq`? * More-ergonomic comparisons between `Label` and `LabelId`. * Move `Dyn{Eq, Hash,Clone}` somewhere else. * Some API to make interning dynamic labels easier. * Optimize string representation * Empty string for unit structs -- no debug info but faster comparisons * Don't show enum types -- same tradeoffs as asbove.
Objective
*Label
types #4954{System, App, *}Label
APIs.Solution
For the sake of brevity I will only refer to
SystemLabel
, but everything applies to all of the other label types as well.SystemLabelId
, a lightweight,copy
struct.SystemLabelId
using the traitSystemLabel
.Changelog
SystemLabel
for now, but this should be changed with Remove the ability to use strings as labels #4409 .Migration Guide
Box<dyn SystemLabel>
should be replaced withSystemLabelId
.AsSystemLabel
trait has been modified.as_system_label
now returnsSystemLabelId
, removing an unnecessary level of indirection.Box::leak
. Not recommended.Questions for later
Debug
impl along with#[derive(*Label)]
?as_str()
?Hash
) from builtin*Label
types?Clone, Copy, PartialEq, Eq
?Label
andLabelId
.Dyn{Eq, Hash,Clone}
somewhere else.