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

Don't recompute SymbolExportLevel for upstream crates. #48611

Merged
merged 6 commits into from
Mar 6, 2018

Conversation

michaelwoerister
Copy link
Member

The data collected in #48373 suggests that we can avoid generating up to 30% of the LLVM definitions by only instantiating function monomorphizations once with a given crate graph. Some more data, collected with a proof-of-concept implementation of re-using monomorphizations, which is less efficient than the MIR-only RLIB approach, suggests that it's still around 25% LLVM definitions that we can save.

So far, this PR only cleans up handling of symbol export status. Too early to review still.

@rust-highfive
Copy link
Collaborator

r? @eddyb

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 28, 2018
@michaelwoerister michaelwoerister removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 28, 2018
@pietroalbini pietroalbini added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Feb 28, 2018
@michaelwoerister michaelwoerister force-pushed the share-generics2 branch 2 times, most recently from aac4a2f to 03f384f Compare March 1, 2018 13:12
@michaelwoerister
Copy link
Member Author

@bors try

@bors
Copy link
Contributor

bors commented Mar 1, 2018

⌛ Trying commit 03f384f with merge 1d719d20eb4669ff7545f5d4445975bb1d082f35...

@bors
Copy link
Contributor

bors commented Mar 1, 2018

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

@michaelwoerister
Copy link
Member Author

@Mark-Simulacrum, could you start a perf run for this? It might already bring improvements in the current state (which is still just a refactoring without additional functionality).

@Mark-Simulacrum
Copy link
Member

Perf run queued.

@michaelwoerister
Copy link
Member Author

@Mark-Simulacrum
Copy link
Member

I'm tempted to suggest we land this as-is unless that's a hardship for some reason because it feels like it could give us some fairly amazing wins in the run-pass suite of tests. Does that seem likely/reasonable?

@michaelwoerister
Copy link
Member Author

@Mark-Simulacrum, that's a great idea! It might really help with run-pass.

r? @alexcrichton , if that's OK with you.

@rust-highfive rust-highfive assigned alexcrichton and unassigned eddyb Mar 2, 2018
@michaelwoerister michaelwoerister changed the title [WIP] Allow for re-using monomorphizations from upstream crates. Don't recompute SymbolExportLevel for upstream crates. Mar 2, 2018
@alexcrichton
Copy link
Member

@bors: r+

Nice wins!

@bors
Copy link
Contributor

bors commented Mar 2, 2018

📌 Commit 03f384f has been approved by alexcrichton

@bors bors 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 Mar 2, 2018
@Mark-Simulacrum
Copy link
Member

@bors p=5 -- this can't hurt but if it does improve testing times then we could speed up cycle time

Manishearth added a commit to Manishearth/rust that referenced this pull request Mar 3, 2018
@michaelwoerister
Copy link
Member Author

Rebased.

@bors r=alexcrichton

@bors
Copy link
Contributor

bors commented Mar 5, 2018

📌 Commit 7a008f5 has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Mar 5, 2018

⌛ Testing commit 7a008f5db05e9471fcd17c1717a85247ca65820f with merge 3ff22504c52436459ec0c1716982e429feae394a...

@bors bors added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Mar 6, 2018
@bors
Copy link
Contributor

bors commented Mar 6, 2018

⌛ Testing commit f5ab4d4 with merge b977e04...

bors added a commit that referenced this pull request Mar 6, 2018
Don't recompute SymbolExportLevel for upstream crates.

The data collected in #48373 suggests that we can avoid generating up to 30% of the LLVM definitions by only instantiating function monomorphizations once with a given crate graph. Some more data, collected with a [proof-of-concept implementation](https://github.com/michaelwoerister/rust/commits/share-generics) of re-using monomorphizations, which is less efficient than the MIR-only RLIB approach, suggests that it's still around 25% LLVM definitions that we can save.

So far, this PR only cleans up handling of symbol export status. Too early to review still.
@bors
Copy link
Contributor

bors commented Mar 6, 2018

💔 Test failed - status-appveyor

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 6, 2018
@michaelwoerister
Copy link
Member Author

AppVeyor timeout 😭

@alexcrichton
Copy link
Member

All dist jobs passed, merging manually

@alexcrichton alexcrichton merged commit f5ab4d4 into rust-lang:master Mar 6, 2018
bors added a commit that referenced this pull request Mar 20, 2018
Allow for re-using monomorphizations in upstream crates.

Followup to #48611. This implementation is pretty much finished modulo failing tests if there are any. Not quite ready for review yet though.

### DESCRIPTION

This PR introduces a `share-generics` mode for RLIBs and Rust dylibs. When a crate is compiled in this mode, two things will happen:
- before instantiating a monomorphization in the current crate, the compiler will look for that monomorphization in all upstream crates and link to it, if possible.
- monomorphizations are not internalized during partitioning. Instead they are added to the list of symbols exported from the crate.

This results in less code being translated and LLVMed. However, there are also downsides:
- it will impede optimization somewhat, since fewer functions can be internalized, and
- Rust dylibs will have bigger symbol tables since they'll also export monomorphizations.

Consequently, this PR only enables the `shared-generics` mode for opt-levels `No`, `Less`, `Size`, and `MinSize`, and for when incremental compilation is activated. `-O2` and `-O3` will still generate generic functions per-crate.

Another thing to note is that this has a somewhat similar effect as MIR-only RLIBs, in that monomorphizations are shared, but it is less effective because it cannot share monomorphizations between sibling crates:

```
         A        <--- defines `fn foo<T>() { .. }`
       /   \
      /     \
     B       C    <--- both call `foo<u32>()`
      \     /
       \   /
         D        <--- calls `foo<u32>()` too
```

With `share-generics`, both `B` and `C` have to instantiate `foo<u32>` and only `D` can re-use it (from either `B` or `C`). With MIR-only RLIBs, `B` and `C` would not instantiate anything, and in `D` we would then only instantiate `foo<u32>` once.
On the other hand, when there are many leaf crates in the graph (e.g. when compiling many individual test binaries) then the `share-generics` approach will often be more effective.

### TODO
 - [x] Add codegen test that makes sure monomorphizations can be internalized in non-Rust binaries.
 - [x] Add codegen-units test that makes sure we share generics.
 - [x] Add run-make test that makes sure we don't export any monomorphizations from non-Rust binaries.
 - [x] Review for reproducible-builds implications.
bors added a commit that referenced this pull request Mar 22, 2018
Allow for re-using monomorphizations in upstream crates.

Followup to #48611. This implementation is pretty much finished modulo failing tests if there are any. Not quite ready for review yet though.

### DESCRIPTION

This PR introduces a `share-generics` mode for RLIBs and Rust dylibs. When a crate is compiled in this mode, two things will happen:
- before instantiating a monomorphization in the current crate, the compiler will look for that monomorphization in all upstream crates and link to it, if possible.
- monomorphizations are not internalized during partitioning. Instead they are added to the list of symbols exported from the crate.

This results in less code being translated and LLVMed. However, there are also downsides:
- it will impede optimization somewhat, since fewer functions can be internalized, and
- Rust dylibs will have bigger symbol tables since they'll also export monomorphizations.

Consequently, this PR only enables the `shared-generics` mode for opt-levels `No`, `Less`, `Size`, and `MinSize`, and for when incremental compilation is activated. `-O2` and `-O3` will still generate generic functions per-crate.

Another thing to note is that this has a somewhat similar effect as MIR-only RLIBs, in that monomorphizations are shared, but it is less effective because it cannot share monomorphizations between sibling crates:

```
         A        <--- defines `fn foo<T>() { .. }`
       /   \
      /     \
     B       C    <--- both call `foo<u32>()`
      \     /
       \   /
         D        <--- calls `foo<u32>()` too
```

With `share-generics`, both `B` and `C` have to instantiate `foo<u32>` and only `D` can re-use it (from either `B` or `C`). With MIR-only RLIBs, `B` and `C` would not instantiate anything, and in `D` we would then only instantiate `foo<u32>` once.
On the other hand, when there are many leaf crates in the graph (e.g. when compiling many individual test binaries) then the `share-generics` approach will often be more effective.

### TODO
 - [x] Add codegen test that makes sure monomorphizations can be internalized in non-Rust binaries.
 - [x] Add codegen-units test that makes sure we share generics.
 - [x] Add run-make test that makes sure we don't export any monomorphizations from non-Rust binaries.
 - [x] Review for reproducible-builds implications.
bors added a commit that referenced this pull request Apr 6, 2018
Allow for re-using monomorphizations in upstream crates.

Followup to #48611. This implementation is pretty much finished modulo failing tests if there are any. Not quite ready for review yet though.

### DESCRIPTION

This PR introduces a `share-generics` mode for RLIBs and Rust dylibs. When a crate is compiled in this mode, two things will happen:
- before instantiating a monomorphization in the current crate, the compiler will look for that monomorphization in all upstream crates and link to it, if possible.
- monomorphizations are not internalized during partitioning. Instead they are added to the list of symbols exported from the crate.

This results in less code being translated and LLVMed. However, there are also downsides:
- it will impede optimization somewhat, since fewer functions can be internalized, and
- Rust dylibs will have bigger symbol tables since they'll also export monomorphizations.

Consequently, this PR only enables the `shared-generics` mode for opt-levels `No`, `Less`, `Size`, and `MinSize`, and for when incremental compilation is activated. `-O2` and `-O3` will still generate generic functions per-crate.

Another thing to note is that this has a somewhat similar effect as MIR-only RLIBs, in that monomorphizations are shared, but it is less effective because it cannot share monomorphizations between sibling crates:

```
         A        <--- defines `fn foo<T>() { .. }`
       /   \
      /     \
     B       C    <--- both call `foo<u32>()`
      \     /
       \   /
         D        <--- calls `foo<u32>()` too
```

With `share-generics`, both `B` and `C` have to instantiate `foo<u32>` and only `D` can re-use it (from either `B` or `C`). With MIR-only RLIBs, `B` and `C` would not instantiate anything, and in `D` we would then only instantiate `foo<u32>` once.
On the other hand, when there are many leaf crates in the graph (e.g. when compiling many individual test binaries) then the `share-generics` approach will often be more effective.

### TODO
 - [x] Add codegen test that makes sure monomorphizations can be internalized in non-Rust binaries.
 - [x] Add codegen-units test that makes sure we share generics.
 - [x] Add run-make test that makes sure we don't export any monomorphizations from non-Rust binaries.
 - [x] Review for reproducible-builds implications.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants