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

[Incremental] Cache hashes for AdDef and ty::Slice<T> #47373

Merged
merged 2 commits into from
Jan 23, 2018

Conversation

wesleywiser
Copy link
Member

}

let hash = CACHE.with(|cache| {
let addr = &**self as *const ty::Slice<T> as *const usize as usize;
Copy link
Member Author

@wesleywiser wesleywiser Jan 12, 2018

Choose a reason for hiding this comment

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

Can you check this? I tried self as *const ty::Slice<T> as usize but got a casting error. The suggested fix in #41300 resolved the error but I'm not really sure why it works.


let hash = CACHE.with(|cache| {
let addr = self as *const AdtDef as usize;
if let Some(&hash) = cache.borrow().get(&addr) {
Copy link
Member

Choose a reason for hiding this comment

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

Since AdtDefs are not recursive, you should be able to slightly optimize this by using HashMap::entry(). That avoids having to look up the key twice in the "cache miss" case.

You cannot do the same for ty::Slice because while hashing one slice, you might encounter a nested one somewhere down the line and consequently run into a RefCell double-borrow panic.

@@ -1483,10 +1485,29 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for AdtDef {
ref repr,
} = *self;
Copy link
Member

Choose a reason for hiding this comment

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

I would move this whole block into the closure, after the "cache hit" case.

@michaelwoerister
Copy link
Member

Right, a &ty::Slice<T> is a "fat pointer" because the [T] in the slice is of unknown size. When pointing to unsized things (like trait objects or slices) the compiler not only has to store the address of the thing but also its size/length in the pointer (which is what makes the pointer fat).

What you did should be correct but is a bit roundabout. First you are converting self which is a "fat" reference into a "fat" raw pointer (*const ty::Slice<T>) and that into a "thin" raw pointer (*const usize) and finally that into a usize.

I would suggest that you do the same thing as the Hash implementation for ty::Slice does:

(self.as_ptr(), self.len()).hash(s)

This makes use of the Deref implementation for ty::Slice. When calling as_ptr() on the self, the compiler will first auto-deref the ty::Slice<T> to a regular &[T] and then invoke as_ptr() on that. as_ptr() already returns a thin pointer (*const T), so we are fine.

Since the Hash implementation also takes the length of slice into account, I think we should do so too. It's possible that the interner stores some of these slices overlapped. That is, in theory, if you have two slices &[1,2,3] and &[1,2,3,4,5], you can store only the longer one and then point the shorter one to the same address, just with the shorter length. Not sure if that actually happens (if it does then the PartialEq implementation of ty::Slice is buggy [cc @eddyb]) but let's stay on the safe side.

So I would make the cache key (usize, usize) for address and length in the ty::Slice case, constructed simply by (self.as_ptr() as usize, self.len()).

@eddyb
Copy link
Member

eddyb commented Jan 12, 2018

ty::Slice can't be sliced further, so the PartialEq impl shouldn't be problematic in practice.

@shepmaster shepmaster added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 13, 2018
@wesleywiser
Copy link
Member Author

Thanks @michaelwoerister! I think I've addressed all of your concerns in the latest revisions.

Copy link
Member

@michaelwoerister michaelwoerister 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! If you remove that redundant line I commented on below, this should be ready for a performance test.

repr.hash_stable(hcx, &mut hasher);

let hash: Fingerprint = hasher.finish();
(addr, hash);
Copy link
Member

Choose a reason for hiding this comment

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

This line seems to be a leftover from something.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, I'm not even sure where that came from lol

@wesleywiser
Copy link
Member Author

Fixed

@michaelwoerister
Copy link
Member

Excellent. I'll start a try-build so we can measure the performance impact.

@bors try

@bors
Copy link
Contributor

bors commented Jan 16, 2018

⌛ Trying commit 45bd091 with merge 1304b66...

bors added a commit that referenced this pull request Jan 16, 2018
[Incremental] Cache hashes for AdDef and ty::Slice<T>

r? @michaelwoerister
@bors
Copy link
Contributor

bors commented Jan 16, 2018

☀️ Test successful - status-travis
State: approved= try=True

@Mark-Simulacrum
Copy link
Member

Perf queued.

@michaelwoerister
Copy link
Member

michaelwoerister commented Jan 16, 2018

perf.rlo link (doesn't work yet works now)

@michaelwoerister
Copy link
Member

Nice! These are some pretty good performance improvements. If it doesn't cause any trouble with further testing, we might even want to backport it to the current beta, given how small the change set is. Thank you, @wesleywiser!

@bors r+

@bors
Copy link
Contributor

bors commented Jan 17, 2018

📌 Commit 45bd091 has been approved by michaelwoerister

@wesleywiser
Copy link
Member Author

Thanks @michaelwoerister!

@carols10cents carols10cents added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jan 22, 2018
@bors
Copy link
Contributor

bors commented Jan 22, 2018

⌛ Testing commit 45bd091 with merge 47a8eb7...

bors added a commit that referenced this pull request Jan 22, 2018
…ster

[Incremental] Cache hashes for AdDef and ty::Slice<T>

r? @michaelwoerister
@bors
Copy link
Contributor

bors commented Jan 23, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: michaelwoerister
Pushing 47a8eb7 to master...

@bors bors merged commit 45bd091 into rust-lang:master Jan 23, 2018
@michaelwoerister
Copy link
Member

Very good numbers for a single optimization :)

http://perf.rust-lang.org/compare.html?start=ae920dcc98c9b18b38aac03367f7f1cd6dce7d2d&end=47a8eb7c4e24b61a8a9ab4eaff60ef65291aaa56&stat=instructions%3Au

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants