-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Optimize layout of TypeVariants #50395
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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.
Thank you, @Zoxc! Looks beautiful! :)
You should definitely add a regression test that makes sure that TypeVariants
stays at 24 bytes. Would be a shame if it grew again (without good reason).
I've added some comments to the first commit. The other commits look good to me. It would be great though, if someone else could take a look at the GeneratorSubsts
change, since I don't know that code too well.
src/librustc/lib.rs
Outdated
@@ -40,6 +40,7 @@ | |||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico", | |||
html_root_url = "https://doc.rust-lang.org/nightly/")] | |||
|
|||
#![feature(asm)] |
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.
Why is this needed?
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.
It not. I've removed it.
src/librustc/ty/context.rs
Outdated
let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v)); | ||
let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v); | ||
// Cast to 'gcx | ||
let i = unsafe { mem::transmute(i) }; |
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.
Making this let i: &'gcx $ty = ...
would make it even more explicit.
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.
That doesn't work since $ty
uses 'tcx
lifetimes, hence the need for transmute
.
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 mean that the transmute should be removed, rather that the binding is explicitly annotated for more clarity:
let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
// Cast to 'gcx
let i: &'gcx $ty = unsafe { mem::transmute(i) };
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 think @Zoxc's point is that $ty
already has explicit lifetimes in it, so it wouldn't work.
OTOH, since this is a reference, maybe pointer casting should be used?
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 can probably just refactor the macros to get rid of the transmute here.
src/librustc/ty/mod.rs
Outdated
@@ -566,18 +568,75 @@ impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> { | |||
} | |||
} | |||
|
|||
extern { | |||
type Unsized; |
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.
This could have a more descriptive name, such as OpaqueSliceContents
.
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've renamed it to that.
src/librustc/ty/mod.rs
Outdated
// Align up the size of the len (usize) field | ||
let align = mem::align_of::<T>(); | ||
let align_mask = align - 1; | ||
let offset = mem::size_of::<usize>(); |
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.
A u32
for the length would probably be enough in practice.
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.
Perhaps. I don't think we have many 4-byte aligned types in slices though.
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.
That's true. Nevermind then.
src/librustc/ty/mod.rs
Outdated
|
||
let mem: *mut u8 = &mut arena.alloc_raw( | ||
size, | ||
cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()))[0]; |
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.
You could use .as_mut_ptr()
here, I think.
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.
Done.
src/librustc/ty/mod.rs
Outdated
&self.0 | ||
unsafe { | ||
if self as *const _ as usize == EMPTY_SLICE { | ||
return mem::transmute(slice::from_raw_parts(mem::align_of::<T>() as *const T, 0)) |
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.
You might be able to just return &[]
here?
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.
Done.
@bors p=1 (this is likely to bitrot) |
r? @eddyb (for reviewing the commit that introduces |
src/librustc/util/common.rs
Outdated
// Trigger a debugger if we crashed during bootstrap | ||
DebugBreak(); | ||
} | ||
eprintln!("PANIC HOOK END"); |
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.
Revert these?
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.
Done.
119916b
to
9973dea
Compare
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@@ -888,9 +888,10 @@ for ty::TypeVariants<'gcx> | |||
TyRawPtr(pointee_ty) => { | |||
pointee_ty.hash_stable(hcx, hasher); | |||
} | |||
TyRef(region, pointee_ty) => { | |||
TyRef(region, pointee_ty, mutbl) => { |
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.
Why not also change TyRawPtr
and maybe getting rid of TypeAndMut
?
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.
Because it's additional work which does not further reduce the size of TypeVariants
. It probably would be a bit cleaner though.
So this PR looks relatively okay (the generator parts especially). |
I've removed the commit for thin slices. It caused linking errors after I rebased this PR. |
That's weird. Did the commit introduce some instability in symbol hashes? |
@bors try |
Optimize layout of TypeVariants This makes references to `Slice` use thin pointers by storing the slice length in the slice itself. `GeneratorInterior` is replaced by storing the movability of generators in `TyGenerator` and the interior witness is stored in `GeneratorSubsts` (which is just a wrapper around `&'tcx Substs`, like `ClosureSubsts`). Finally the fields of `TypeAndMut` is stored inline in `TyRef`. These changes combine to reduce `TypeVariants` from 48 bytes to 24 bytes on x86_64. r? @michaelwoerister
☀️ Test successful - status-travis |
@Mark-Simulacrum I'd like a perf run here |
The perf results show runtime improved in some cases and degraded in others. It's mostly noise, I'd say. |
Some sort of memory usage benchmark would be interesting for this. |
@bors r=michaelwoerister |
📌 Commit c9d9c24 has been approved by |
⌛ Testing commit c9d9c24 with merge 25a79f6b346ed8e0c43d313fab38a206b06677e3... |
💔 Test failed - status-travis |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@bors retry |
Optimize layout of TypeVariants This makes references to `Slice` use thin pointers by storing the slice length in the slice itself. `GeneratorInterior` is replaced by storing the movability of generators in `TyGenerator` and the interior witness is stored in `GeneratorSubsts` (which is just a wrapper around `&'tcx Substs`, like `ClosureSubsts`). Finally the fields of `TypeAndMut` is stored inline in `TyRef`. These changes combine to reduce `TypeVariants` from 48 bytes to 24 bytes on x86_64. r? @michaelwoerister
☀️ Test successful - status-appveyor, status-travis |
📣 Toolstate changed by #50395! Tested on commit 0a223d1. 💔 clippy-driver on windows: test-pass → build-fail (cc @Manishearth @llogiq @mcarton @oli-obk, @rust-lang/infra). |
Tested on commit rust-lang/rust@0a223d1. Direct link to PR: <rust-lang/rust#50395> 💔 clippy-driver on windows: test-pass → build-fail (cc @Manishearth @llogiq @mcarton @oli-obk, @rust-lang/infra). 💔 clippy-driver on linux: test-pass → build-fail (cc @Manishearth @llogiq @mcarton @oli-obk, @rust-lang/infra). 💔 miri on windows: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb, @rust-lang/infra). 💔 miri on linux: test-pass → build-fail (cc @oli-obk @RalfJung @eddyb, @rust-lang/infra).
Make &Slice a thin pointer Split out from #50395 r? @michaelwoerister
Make &Slice a thin pointer Split out from #50395 r? @michaelwoerister
This makes references to
Slice
use thin pointers by storing the slice length in the slice itself.GeneratorInterior
is replaced by storing the movability of generators inTyGenerator
and the interior witness is stored inGeneratorSubsts
(which is just a wrapper around&'tcx Substs
, likeClosureSubsts
). Finally the fields ofTypeAndMut
is stored inline inTyRef
. These changes combine to reduceTypeVariants
from 48 bytes to 24 bytes on x86_64.r? @michaelwoerister