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

[MIR] Cache drops for early scope exits #34307

Merged
merged 1 commit into from
Jun 17, 2016
Merged

Conversation

nagisa
Copy link
Member

@nagisa nagisa commented Jun 16, 2016

Previously we would rebuild all drops on every early exit from a scope, which for code like:

match x {
    A => return 1,
    B => return 2,
    ...
    C => return 27
}

would produce 27 exactly same chains of drops for each return, basically a O(n*m) explosion. This is such a case for a match on 80-variant enum with 3 droppable variables in scope.

For ::core::iter::Iterator::partial_cmp the CFG looked like this (after initial SimplifyCfg). With this patch the CFG looks like this instead.

Some numbers (overall very small wins, however neither of the crates have many cases which abuse this corner case):

old time old rss new time new rss
core dump 0.879 224MB 0.871 223MB
core MIR passes 0.759 224MB 0.718 223MB
core MIR codegen passes 1.762 230MB 1.442 228MB
core trans 3.263 279MB 3.116 278MB
core llvm passes 5.611 263MB 5.565 263MB
std dump 0.487 190MB 0.475 192MB
std MIR passes 0.311 190MB 0.288 192MB
std MIR codegen passes 0.753 195MB 0.720 197MB
std trans 2.589 287MB 2.523 287MB
std llvm passes 7.268 245MB 7.447 246MB

@rust-highfive
Copy link
Collaborator

r? @arielb1

(rust_highfive has picked a reviewer for you, use r? to override)

@nagisa
Copy link
Member Author

nagisa commented Jun 16, 2016

cc @eddyb (the patch you wanted to see)

/// each of those has their own cached-blocks, which will branch
/// to this point.
cached_block: Option<BasicBlock>
/// The cache for drop chain on “normal” exit into a particular BasicBlock.
Copy link
Member

Choose a reason for hiding this comment

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

Are the fancy quotes intentional here?

Copy link
Member Author

@nagisa nagisa Jun 16, 2016

Choose a reason for hiding this comment

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

Yes. These are preferred characters for quotation characters in english prose.

Previously we would rebuild all drops on every early exit from a scope, which for code like:

```rust
match x {
    a => return 1,
    b => return 2,
    ...
    z => return 27
}
```

would produce 27 exactly same chains of drops for each return, a O(n*m) explosion in drops.
@arielb1
Copy link
Contributor

arielb1 commented Jun 16, 2016

@bors r+

@bors
Copy link
Contributor

bors commented Jun 16, 2016

📌 Commit 04d63cc has been approved by arielb1

Manishearth added a commit to Manishearth/rust that referenced this pull request Jun 16, 2016
[MIR] Cache drops for early scope exits

Previously we would rebuild all drops on every early exit from a scope, which for code like:

```rust
match x {
    A => return 1,
    B => return 2,
    ...
    C => return 27
}
```

would produce 27 exactly same chains of drops for each return, basically a `O(n*m)` explosion. [This](https://cloud.githubusercontent.com/assets/679122/16125192/3355e32c-33fb-11e6-8564-c37cab2477a0.png) is such a case for a match on 80-variant enum with 3 droppable variables in scope.

For [`::core::iter::Iterator::partial_cmp`](https://github.com/rust-lang/rust/blob/6edea2cfda2818f0a76f4bac2d18a30feb54c137/src/libcore/iter/iterator.rs#L1909) the CFG looked like [this](https://cloud.githubusercontent.com/assets/679122/16122708/ce0024d8-33f0-11e6-93c2-e1c44b910db2.png) (after initial SimplifyCfg). With this patch the CFG looks like [this](https://cloud.githubusercontent.com/assets/679122/16122806/294fb16e-33f1-11e6-95f6-16c5438231af.png) instead.

Some numbers (overall very small wins, however neither of the crates have many cases which abuse this corner case):

|                         | old time | old rss | new time | new rss  |
|-------------------------|----------|---------|----------|----------|
| core dump               | 0.879        |   224MB     |   0.871  |  223MB   |
| core MIR passes         | 0.759        | 224MB       | 0.718    | 223MB    |
| core MIR codegen passes | 1.762        | 230MB       | 1.442    | 228MB    |
| core trans              | 3.263        | 279MB       | 3.116    | 278MB    |
| core llvm passes        | 5.611        | 263MB       | 5.565    | 263MB    |
| std dump                | 0.487        |   190MB     |   0.475  |  192MB   |
| std MIR passes          | 0.311       | 190MB       | 0.288    | 192MB    |
| std MIR codegen passes  | 0.753        | 195MB       | 0.720    | 197MB    |
| std trans               | 2.589        | 287MB       | 2.523    | 287MB    |
| std llvm passes         | 7.268        | 245MB       | 7.447    | 246MB    |
bors added a commit that referenced this pull request Jun 17, 2016
Rollup of 4 pull requests

- Successful merges: #34298, #34302, #34307, #34312
- Failed merges:
@bors bors merged commit 04d63cc into rust-lang:master Jun 17, 2016
eddyb added a commit to eddyb/rust that referenced this pull request Aug 18, 2016
Fix the invalidation of the MIR early exit cache

~~The rust-lang#34307 introduced a cache for early exits in order to help with O(n*m) explosion of cleanup blocks but the cache is invalidated incorrectly and I can’t seem to figure out why (caching is hard!)~~

~~Remove the cache for now to fix the immediate correctness issue and worry about the performance later.~~

Cache invalidation got fixed.

Fixes rust-lang#35737

r? @nikomatsakis
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