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

Introduce HashStable trait and base ICH implementations on it. #40878

Merged
merged 1 commit into from
Apr 7, 2017

Conversation

michaelwoerister
Copy link
Member

This PR introduces the HashStable trait which marks that a type can be hashed in a way that is stable across multiple compilation sessions. The PR also moves HIR incr. comp. hashing over to implementations of this trait instead of doing this via a HIR visitor. It also provides many HashStable implementations that are not used yet (e.g. for MIR types) but soon will be used when we directly hash crate metadata for incr. comp.

I've only done superficial performance measurements but it looks like the new implementation is a bit faster than the current one (due, I suppose, to some bugs I fixed and some unnecessary inefficiencies I removed). Here is the time in seconds for the compute_incremental_hashes_map pass for various crates:

OLD NEW
libcore 0.507 0.409
libsyntax 0.320 0.260
librustc 0.730 0.611
librustc_driver 0.024 0.015

Some notes regarding the implementation:

  • Most HashStable implementations are provided via the impl_hash_stable_for! macro (as suggested by @nikomatsakis). This works out quite well. A custom_derive would have been better but Macros 1.1 are not available in the compiler.
  • The trait implementation take care to exhaustively destructure everything they hash so that fields added in the future don't fall through the cracks. This is a bit verbose but I think it's well worth the trouble since we've had quite a few issues with missing fields or visitor callbacks in this area in the past. Most of it is behind the macro anyway.

cc @rust-lang/compiler
r? @nikomatsakis

@michaelwoerister
Copy link
Member Author

Those travis errors seem to indicate that something went wrong when rebasing ontop of the catch changes. Looking into it...

@michaelwoerister
Copy link
Member Author

So, I can reliably reproduce these errors but I can't see how the changes in this PR would have an effect like that :/

@michaelwoerister
Copy link
Member Author

OK, the problem was that those tests where exercising code paths that would try to hash the DefPath of NodeIds that don't have a corresponding DefId.

@bors
Copy link
Contributor

bors commented Mar 30, 2017

☔ The latest upstream changes (presumably #40597) made this pull request unmergeable. Please resolve the merge conflicts.

@michaelwoerister
Copy link
Member Author

This latest error is legitimate (the SVH is more sensitive than it needs to be) and I figured out that impl specialization offers a way of solving this in a nice and general way, that also allows for reverting the splitting-out of dep_graph_assert attrs. Please hold off on reviewing until I've done that.

@michaelwoerister michaelwoerister force-pushed the dmh branch 2 times, most recently from 4589028 to 7684437 Compare March 30, 2017 13:28
@michaelwoerister
Copy link
Member Author

Alright, this passes make check for me now and the implementation is simpler too. Hurray specialization!

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Apr 3, 2017

📌 Commit 7684437 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Apr 3, 2017

⌛ Testing commit 7684437 with merge 730547d...

@bors
Copy link
Contributor

bors commented Apr 3, 2017

💔 Test failed - status-travis

@alexcrichton
Copy link
Member

alexcrichton commented Apr 3, 2017 via email

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 6, 2017
Introduce HashStable trait and base ICH implementations on it.

This PR introduces the `HashStable` trait which marks that a type can be hashed in a way that is stable across multiple compilation sessions. The PR also moves HIR incr. comp. hashing over to implementations of this trait instead of doing this via a HIR visitor. It also provides many `HashStable` implementations that are not used yet (e.g. for MIR types) but soon will be used when we directly hash crate metadata for incr. comp.

I've only done superficial performance measurements but it looks like the new implementation is a bit faster than the current one (due, I suppose, to some bugs I fixed and some unnecessary inefficiencies I removed). Here is the time in seconds for the `compute_incremental_hashes_map` pass for various crates:

|                 |  OLD  |  NEW  |
|:---------------:|:-----:|:-----:|
| libcore         | 0.507 | 0.409 |
| libsyntax       | 0.320 | 0.260 |
| librustc        | 0.730 | 0.611 |
| librustc_driver | 0.024 | 0.015 |

Some notes regarding the implementation:
* Most `HashStable` implementations are provided via the `impl_hash_stable_for!` macro (as suggested by @nikomatsakis). This works out quite well. A custom_derive would have been better but Macros 1.1 are not available in the compiler.
* The trait implementation take care to exhaustively destructure everything they hash so that fields added in the future don't fall through the cracks. This is a bit verbose but I think it's well worth the trouble since we've had quite a few issues with missing fields or visitor callbacks in this area in the past. Most of it is behind the macro anyway.

cc @rust-lang/compiler
r? @nikomatsakis
@frewsxcv
Copy link
Member

frewsxcv commented Apr 6, 2017

Ran into an issue with this PR in the rollup

https://travis-ci.org/rust-lang/rust/jobs/219131927

@bors r-

@nikomatsakis
Copy link
Contributor

@michaelwoerister

Looks like a minor merge thing-y:

[00:06:09] error[E0026]: struct `hir::Block` does not have a field named `break_to_expr_id`
[00:06:09]    --> /checkout/src/librustc/ich/impls_hir.rs:347:13
[00:06:09]     |
[00:06:09] 347 |             break_to_expr_id,
[00:06:09]     |             ^^^^^^^^^^^^^^^^ struct `hir::Block` does not have field `break_to_expr_id`
[00:06:09] 
[00:06:09] error[E0027]: pattern does not mention field `targeted_by_break`
[00:06:09]    --> /checkout/src/librustc/ich/impls_hir.rs:341:13
[00:06:09]     |
[00:06:09] 341 |           let hir::Block {
[00:06:09]     |  _____________^ starting here...
[00:06:09] 342 | |             ref stmts,
[00:06:09] 343 | |             ref expr,
[00:06:09] 344 | |             id,
[00:06:09] 345 | |             rules,
[00:06:09] 346 | |             span,
[00:06:09] 347 | |             break_to_expr_id,
[00:06:09] 348 | |         } = *self;
[00:06:09]     | |_________^ ...ending here: missing field `targeted_by_break`
[00:06:09] 
[00:06:15] error: aborting due to 2 previous errors

@nikomatsakis
Copy link
Contributor

In particular I renamed break_to_expr_id to targeted_by_break

This initial commit provides implementations for HIR, MIR, and
everything that also needs to be supported for those two.
@michaelwoerister
Copy link
Member Author

@bors r=nikomatsakis

Rebased.

@bors
Copy link
Contributor

bors commented Apr 6, 2017

📌 Commit c47cdc0 has been approved by nikomatsakis

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 6, 2017
Introduce HashStable trait and base ICH implementations on it.

This PR introduces the `HashStable` trait which marks that a type can be hashed in a way that is stable across multiple compilation sessions. The PR also moves HIR incr. comp. hashing over to implementations of this trait instead of doing this via a HIR visitor. It also provides many `HashStable` implementations that are not used yet (e.g. for MIR types) but soon will be used when we directly hash crate metadata for incr. comp.

I've only done superficial performance measurements but it looks like the new implementation is a bit faster than the current one (due, I suppose, to some bugs I fixed and some unnecessary inefficiencies I removed). Here is the time in seconds for the `compute_incremental_hashes_map` pass for various crates:

|                 |  OLD  |  NEW  |
|:---------------:|:-----:|:-----:|
| libcore         | 0.507 | 0.409 |
| libsyntax       | 0.320 | 0.260 |
| librustc        | 0.730 | 0.611 |
| librustc_driver | 0.024 | 0.015 |

Some notes regarding the implementation:
* Most `HashStable` implementations are provided via the `impl_hash_stable_for!` macro (as suggested by @nikomatsakis). This works out quite well. A custom_derive would have been better but Macros 1.1 are not available in the compiler.
* The trait implementation take care to exhaustively destructure everything they hash so that fields added in the future don't fall through the cracks. This is a bit verbose but I think it's well worth the trouble since we've had quite a few issues with missing fields or visitor callbacks in this area in the past. Most of it is behind the macro anyway.

cc @rust-lang/compiler
r? @nikomatsakis
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 6, 2017
Introduce HashStable trait and base ICH implementations on it.

This PR introduces the `HashStable` trait which marks that a type can be hashed in a way that is stable across multiple compilation sessions. The PR also moves HIR incr. comp. hashing over to implementations of this trait instead of doing this via a HIR visitor. It also provides many `HashStable` implementations that are not used yet (e.g. for MIR types) but soon will be used when we directly hash crate metadata for incr. comp.

I've only done superficial performance measurements but it looks like the new implementation is a bit faster than the current one (due, I suppose, to some bugs I fixed and some unnecessary inefficiencies I removed). Here is the time in seconds for the `compute_incremental_hashes_map` pass for various crates:

|                 |  OLD  |  NEW  |
|:---------------:|:-----:|:-----:|
| libcore         | 0.507 | 0.409 |
| libsyntax       | 0.320 | 0.260 |
| librustc        | 0.730 | 0.611 |
| librustc_driver | 0.024 | 0.015 |

Some notes regarding the implementation:
* Most `HashStable` implementations are provided via the `impl_hash_stable_for!` macro (as suggested by @nikomatsakis). This works out quite well. A custom_derive would have been better but Macros 1.1 are not available in the compiler.
* The trait implementation take care to exhaustively destructure everything they hash so that fields added in the future don't fall through the cracks. This is a bit verbose but I think it's well worth the trouble since we've had quite a few issues with missing fields or visitor callbacks in this area in the past. Most of it is behind the macro anyway.

cc @rust-lang/compiler
r? @nikomatsakis
@bors
Copy link
Contributor

bors commented Apr 6, 2017

⌛ Testing commit c47cdc0 with merge 14d938b...

@bors
Copy link
Contributor

bors commented Apr 6, 2017

💔 Test failed - status-appveyor

bors added a commit that referenced this pull request Apr 6, 2017
Rollup of 8 pull requests

- Successful merges: #40878, #40976, #41089, #41090, #41108, #41111, #41112, #41114
- Failed merges:
@bors bors merged commit c47cdc0 into rust-lang:master Apr 7, 2017
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Apr 7, 2017
…shes, r=nikomatsakis

Handle DefPath hashing centrally as part of DefPathTable (+ save work during SVH calculation)

In almost all cases where we construct a `DefPath`, we just hash it and throw it away again immediately.
With this PR, the compiler will immediately compute and store the hash for each `DefPath` as it is allocated. This way we
+ can get rid of any subsequent `DefPath` hash caching (e.g. the `DefPathHashes`),
+ don't need to allocate a transient `Vec` for holding the `DefPath` (although I'm always surprised how little these small, dynamic allocations seem to hurt performance), and
+ we don't hash `DefPath` prefixes over and over again.

That last part is because we construct the hash for `prefix::foo` by hashing `(hash(prefix), foo)` instead of hashing every component of prefix.

The last commit of this PR is pretty neat, I think:
```
The SVH (Strict Version Hash) of a crate is currently computed
by hashing the ICHes (Incremental Computation Hashes) of the
crate's HIR. This is fine, expect that for incr. comp. we compute
two ICH values for each HIR item, one for the complete item and
one that just includes the item's interface. The two hashes are
are needed for dependency tracking but if we are compiling
non-incrementally and just need the ICH values for the SVH,
one of them is enough, giving us the opportunity to save some
work in this case.
```

r? @nikomatsakis

This PR depends on rust-lang#40878 to be merged first (you can ignore the first commit for reviewing, that's just rust-lang#40878).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants