-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Missed enum layout optimization with a NonZeroU64 + more space in an enum #101567
Comments
Wouldn't it cause severe performance issue for enum with a number of variants? It makes a single-variant check It's really a trade-off instead of an optimization. enum Enum {
_0000, // .0 == 0 && .1 == 0 && .2 == 0 && .3 == 0
_0001, // .0 == 0 && .1 == 0 && .2 == 0 && .3 != 0
_0010,
_0011,
// ...
_1110,
_1111(Box<()>, Box<()>, Box<()>, Box<()>),
} |
It optimizes space usage, but overall I agree it's a tradeoff. We might want attributes like |
Why
|
There's even more generality. You don't even need the second field to have any "invalid values" at all. Even if the original enum had only one use std::num::NonZeroU64;
pub enum Provenance2 {
Concrete {
alloc_id: NonZeroU64,
sb: u64,
},
Wildcard, // .0 = 0, .1 = 0
None, // .0 = 0, .1 = 1
} |
Related, if you have: pub enum Provenance {
Concrete {
alloc_id: NonZeroU64,
sb: NonZeroU64,
},
Wildcard,
} This does niche to 16 bytes, but |
Yeah, that is the case we need for Miri. But I figured we would start with the one where it is all a single enum as that should be easier?
|
Hmm, actually the |
@rustbot label T-compiler A-layout |
I'm working on this. I'm introducing the concept of a I've also got a commit to improve the flexibility of niche-optimized enums by allowing the fields of a tagged variant to go around the niche, with some appearing before and some after. And I've got a commit to allow layouts to store more than just the I should have a PR pretty soon. |
Also: Try to fit other variants by moving fields around the niche. Keep multiple niches, not just the largest one. Look for multiple largest variants. Introduce repr(flag). Fixes rust-lang#101567
I found something similar to this today, but I am not sure if the "flag" method described in this thread works for it. I have an enum like below: pub enum Foo {
One(NonZeroU64, u64),
Two(NonZeroU64),
// Three
}
That surprised me particularly in the case of |
The
Provenance
type defined here is 24 bytes in size:However, it should be possible to encode
Provenance
in 16 bytes: e.g.(0usize, 0suize)
could encodeNone
and(0usize, 1usize)
could encodeWildcard
.In Miri, a slight variant of this would help reduce the size of a fairly common type from 32 bytes to 24 bytes.
Unfortunately even #94075 does not help here. The entire concept of reading a single field to determine the discriminant is not flexible enough to represent this layout.
The text was updated successfully, but these errors were encountered: