-
Notifications
You must be signed in to change notification settings - Fork 12.1k
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
Use the "efficient "pivot pointer" scheme" for Rc<Trait> #54898
Comments
cc @nikomatsakis @RalfJung @rkruppe @gankro @nagisa This is about having e.g. EDIT: similar, but not identical! |
I'm not sure what the expected benefit is. For That might be nice for Rc to avoid the "fetch align from vtable and align Otherwise it doesn't seem worthwhile since it's just a constant offset -- literally one ALU instruction in the worst case, and very often that offset can be folded into subsequent offset calculations or memory accesses (and on x86, even into arithmetic). |
EDIT: see #54898 (comment), it's subtly different: all fields are at constant offsets from the pointer. I'd be curious to see some numbers. There were some claims that this sort of scheme has its benefits, years ago, and I'm not sure how much backing they have (other than other languages doing it). |
Penalizing clone/drop in favour of deref sounds like a pretty decent tradeoff to me? Reference count traffic is much lower in Rust than any other language thanks to the borrowchecker. Also I would expect this change to be a net win on codesize, which is nice. |
Another place where pivots could be useful: We can make |
@rkruppe Ahhh I just realized there's some confusion! You wrote:
But there's no need for complex calculation anywhere! I think you can even prove that no matter which field is the "pivot", the total size of the struct can't. |
With trait objects (or more generally DSTs other than slices), there currently has to be a variable amount of padding between the the refcounts and the T. If you put offset 0 before that padding, the refcount / metadata can be accessed at a constant offset, but then you need an "round up to runtime alignment" calculation to get at the T. If you put offset 0 at the start of the T, the variable padding is before offset 0 and you need a "round down to usize align" step to skip over that padding and get at the usizes. I guess you're trying to say we should put that padding at the start of the layout so we get [padding, refcounts/metadata, data] instead of [refcounts/metadata, padding, data]? That would require deeper changes to layout than just storing the |
@rkruppe The changes are pretty straight-forward, the pivot opt-in would mean the fields in the struct keep their definition order, so all you have to do is compute offsets twice, once for fields before the pivot, and once for fields after (including the pivot). I mean, yes, there's some effort involved in allowing signed offsets, but they would still be constant. We already have to deal with weird layouts because of enum variants, I don't think this would be much more of a hassle. In terms of LLVM, the struct type we give it will not include fields before the pivot, which will have to be accessed in a different way. EDIT: hmm, I haven't considered pivoted structs nested in other structs. So it's more like there are two field directions, each with their own extent (but common alignment). What should EDIT: What about arrays of I guess we limit the problems by limiting it to unstable code and requiring pivoted structs to be private (meaning they're never exposed in a way that stable code can see them). |
I'm deferring to you on implementation effort, I was mostly reacting to "oh we can test this by storing |
@rkruppe Right, that was a mistake, my bad - we can still test it, it's just a bit more effort than reusing code from Also, I added a few edits to the previous post because I overlooked a few aspects, regarding the conceptual consequences, which might be worse than implementation. |
@eddyb Why would layout have to be involved? This could all be done by |
I am imagining a library that takes two types (the part The alignment of the allocation must be the max of the two alignments of |
@RalfJung Ah, doing this with a library pointer type makes a lot of sense! (I don't know why @nikomatsakis and I didn't consider this - maybe it was before we had a solid story for DSTs, and it was a possible way to implement DST fields without dynamic alignment) |
Just for historical records: I asked the swift devs if they ever messed around with this stuff (they have super optimized their (A)Rc since all classes are ref-counted), but they hadn't because they are limited by objc compatibility. |
Refiling what remains of rust-lang/rfcs#981 here...
This might already be done... but @eddyb wrote:
The text was updated successfully, but these errors were encountered: