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

Type walker small vector #37760

Merged
merged 1 commit into from
Nov 23, 2016
Merged

Conversation

nnethercote
Copy link
Contributor

These two changes avoid allocations on some hot paths and speed up a few workloads (some from rustc-benchmarks, as well as the workload from #36799) by 1--2%.

@rust-highfive
Copy link
Collaborator

r? @arielb1

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

@@ -127,6 +127,11 @@ pub enum DepNode<D: Clone + Debug> {
TraitItems(D),
ReprHints(D),
TraitSelect(Vec<D>),
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason we add a TraitSelectSingle instead of making TraitSelect SmallVec<[D; 1]>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did it that way because using SmallVec would likely increase the size of DepNode. But I haven't measured and I'm not sure how much that would matter.

Copy link
Member

Choose a reason for hiding this comment

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

Seems unlikely, but it's possible. SmallVec has no size overhead so long as size_of(D) + size_of(usize) <= size_of(Vec<D>), and I don't know if that's true. DepNode mostly stores either D, Vec<D>, or Arc<WorkProductId>.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For at least one case, it increases the siz of DepNode from 32 bytes to 40 bytes on 64-bit. DepNode is used in HashMaps and Graphs so I'm leery about increasing its size.

while len < self.len() {
// Decrement len before the drop_in_place(), so a panic on Drop
// doesn't re-drop the just-failed value.
let len = self.len() - 1;
Copy link
Member

Choose a reason for hiding this comment

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

this particular shadowing confuses more than it helps; it might as well use a different variable name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can change it, but it's also worth noting that I copied this code (with minor modifications) from vec.rs.

@michaelwoerister
Copy link
Member

Please don't approve this without further review. Adding new kinds of DepNodes should be done carefully. cc @nikomatsakis


// An optional alternative to `TraitSelect` that avoids a heap allocation
// in the case where there is a single D. (Note that `TraitSelect` is still
// allowed to contain a Vec with a single D.)
Copy link
Contributor

Choose a reason for hiding this comment

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

It may be better to avoid vecs altogether and change to

TraitSelect { trait_def_id: DefId, self_def_id: Option<DefId> }

Or:

TraitSelect { trait_def_id: DefId },
TraitSelectNominal { trait_def_id: DefId, self_def_id: DefId },

The idea would be that we just extract the first def-id we find in the self type for the trait, rather than extracting all def-ids that we find in any of the input types. (And, if there is no def-id in the self-type, then we go to the trait-only variant.)

I've not had a lot of coffee yet this morning but off hand that seems fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

(Obviously it will affect incremental resolution, but probably not in any major way -- it's still the case that we can distinguish vec.clone() from string.clone())

Copy link
Contributor

Choose a reason for hiding this comment

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

Sure. I don't think the "type parameter" case is that much important here, and eventually we probably want to rethink how we handle this anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nikomatsakis: I'm having trouble seeing how the Ds in the old TraitSelect variant would map to the Ds in the new one. The two places where a TraitSelect variant is created are TraitPredicate::dep_node and ProjectionCache::to_dep_node. The former is guaranteed to produce a vector of length 1 or more due to the iter::once, but the latter isn't.

Copy link
Member

Choose a reason for hiding this comment

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

Isn't the "correct" thing to use here some form of the fast_reject "type skeletons"?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I tried them and had problems, but now I'm not 100% sure why. I guess because you can't "map" them as easily. You'd have to refactor, and I'm not sure I see the point. The main thing is to ensure that Vec: Clone doesn't interfere with String: Clone and the like.

Copy link
Member

Choose a reason for hiding this comment

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

Btw, looks like ProjectionCache::to_dep_node really wants multiple nodes, could the API be changed to be an "internal iterator" i.e. each_dep_node?

@brson brson added the relnotes Marks issues that should be documented in the release notes of the next release. label Nov 16, 2016
The change also adds the missing `SmallVec::truncate` method.
@nnethercote nnethercote force-pushed the TypeWalker-SmallVector branch from 6db12d4 to f72685f Compare November 21, 2016 23:54
@nnethercote
Copy link
Contributor Author

I updated the PR to cover just the first commit. @nikomatsakis is working on the DepNode code and will post a separate PR for that.

r? @arielb1

@arielb1
Copy link
Contributor

arielb1 commented Nov 22, 2016

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Nov 22, 2016

📌 Commit f72685f has been approved by arielb1

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Nov 23, 2016
… r=arielb1

Type walker small vector

These two changes avoid allocations on some hot paths and speed up a few workloads (some from rustc-benchmarks, as well as the workload from rust-lang#36799) by 1--2%.
bors added a commit that referenced this pull request Nov 23, 2016
Rollup of 7 pull requests

- Successful merges: #37442, #37760, #37836, #37851, #37859, #37913, #37925
- Failed merges:
@bors bors merged commit f72685f into rust-lang:master Nov 23, 2016
@nnethercote nnethercote deleted the TypeWalker-SmallVector branch November 23, 2016 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants