Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd Iterator trait TrustedLen to enable better FromIterator / Extend #37306
Conversation
bluss
added some commits
Oct 20, 2016
rust-highfive
assigned
alexcrichton
Oct 20, 2016
This comment has been minimized.
This comment has been minimized.
|
(rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
|
Benchmark and result at https://gist.github.com/bluss/baa98105d141cff3949dda1c1f2d8cce Using SetLenOnDrop was required to avoid the aliasing troubles in the case of The .chain() cases unfortunately are not optimized well (remains as one loop that goes through the chain's state logic, instead of splitting it into two loops for the front and back part). |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I believe at least this adapter for Result also should have TrustedLen implemented on it: https://github.com/rust-lang/rust/blob/master/src/libcore/result.rs#L997. I know it currently doesn't have a size_hint, but @eddyb had me add it in #37270, since we believe it should have it. |
This comment has been minimized.
This comment has been minimized.
|
@Mark-Simulacrum Thanks. Yes, there's a ton of iterators that will need the marker |
This comment has been minimized.
This comment has been minimized.
|
Nice! Does this mean that we can remove some of the specialization around extending vectors from slices as well? |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton I think it does. We can probably remove .extend_from_slice()'s implementation entirely. |
This comment has been minimized.
This comment has been minimized.
|
Nevermind, extend_from_slice is Clone and extend(&[T]) requires Copy. |
This comment has been minimized.
This comment has been minimized.
|
Ah, that's how to do it. Now extend_from_slice's own implementation is gone, and the specialization that redirected to it. (Sorry #37094 !). I verified performance using a simple benchmark (only). |
This comment has been minimized.
This comment has been minimized.
|
Is the specialization of |
This comment has been minimized.
This comment has been minimized.
|
The more I read this as well the more I feel like we need more eyes on this. This kind of usage of specialization seems like it could make for some really nasty bugs if we get this wrong. Could we perhaps start more conservatively with implementations of The addition of |
This comment has been minimized.
This comment has been minimized.
|
Ah and cc @rust-lang/libs |
This comment has been minimized.
This comment has been minimized.
|
Right, I think it should compile to the same thing. I had the idea that it could reuse I would like to keep the Vec::append specialization, since it's less code for the optimizer to chew on, it doesn't rely on release mode optimizations, and because it's easy to keep what's there. The Range iterators should be unproblematic, given TrustedLen's contract. |
This comment has been minimized.
This comment has been minimized.
|
We in general have a large problem of lots of code to chew on in LLVM, and while specialization can indeed solve a lot of that I'd personally prefer to err on the side of less source code as there's just fewer unsafe blocks and fewer hoops you need to jump through to see how Perhaps some debug assertions could be added to the |
This comment has been minimized.
This comment has been minimized.
|
A reason that there is no I guess we can add a debug assertion to where this is used. |
This comment has been minimized.
This comment has been minimized.
|
|
alexcrichton
added
the
T-libs
label
Oct 25, 2016
This comment has been minimized.
This comment has been minimized.
|
@rfcbot fcp merge I personally feel that we should get rid of the other specialization of
Right it gives LLVM more to chew on, but we've practically never optimized the standard library for minimizing the amount of code we send to LLVM, so I don't think now's really the time to start. Removing the extra specialization keeps it a little more understandable as there's only one specialization to consider, not multiple. |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Oct 25, 2016
•
|
Team member @alexcrichton has proposed to merge this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton Oh, I can be on board with that. As long as Vec::append's own implementation stays as it is. |
This comment has been minimized.
This comment has been minimized.
|
Oh yeah I wouldn't imagine any change to the implementation of |
bluss
added some commits
Oct 26, 2016
This comment has been minimized.
This comment has been minimized.
|
The special case for |
This comment has been minimized.
This comment has been minimized.
|
Benchmark file for this PR https://gist.github.com/bluss/3828cadbd92f5a94d020a474b9879f6c One highlight is the
pub fn map_fast(l: &[(u32, u32)]) -> Vec<u32> {
let mut result = Vec::with_capacity(l.len());
for i in 0..l.len() {
unsafe {
*result.get_unchecked_mut(i) = l[i].0;
result.set_len(i);
}
}
result
}and the other one is just |
This comment has been minimized.
This comment has been minimized.
|
Something that's not in this PR is to replace the for loop in Remember that most of these benchmarks are best cases, where the iterator element is a small value and where loop optimizations like unrolling or converting to memcpy have a big impact. |
brson
added
the
relnotes
label
Nov 1, 2016
This comment has been minimized.
This comment has been minimized.
|
Waiting for @Kimundi to chime in. |
bluss
referenced this pull request
Nov 3, 2016
Open
Tracking issue for TrustedLen (`trusted_len`) #37572
This comment has been minimized.
This comment has been minimized.
|
Opened a tracking issue and linked it in. |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Nov 3, 2016
|
psst @alexcrichton, I wasn't able to add the |
This comment has been minimized.
This comment has been minimized.
|
Looks like travis error is legit? |
bluss
force-pushed the
bluss:trusted-len
branch
from
9688dce
to
f0e6b90
Nov 4, 2016
This comment has been minimized.
This comment has been minimized.
|
Yes, sorry, syntax error in the stability attr. Fixed by amending that commit. |
This comment has been minimized.
This comment has been minimized.
|
@bors: r+ |
This comment has been minimized.
This comment has been minimized.
|
|
jonathandturner
added a commit
to jonathandturner/rust
that referenced
this pull request
Nov 4, 2016
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Nov 4, 2016
This comment has been minimized.
This comment has been minimized.
bors
merged commit f0e6b90
into
rust-lang:master
Nov 4, 2016
bluss
deleted the
bluss:trusted-len
branch
Nov 4, 2016
bluss
referenced this pull request
Jul 16, 2017
Open
Use internal iteration in FromIterator and Extend implementations. #43255
This comment has been minimized.
This comment has been minimized.
|
Was there a particular reason behind not taking advantage of |
This comment has been minimized.
This comment has been minimized.
|
No reason, if it makes sense, just explore it |
bluss commentedOct 20, 2016
•
edited
This trait attempts to improve FromIterator / Extend code by enabling it to trust the iterator to produce an exact number of elements, which means that reallocation needs to happen only once and is moved out of the loop.
TrustedLendiffers fromExactSizeIteratorin that it attempts to include more iterators by allowing for the case that the iterator's len does not fit inusize. Consumers must check for this case (for example they could panic, since they can't allocate a collection of that size).For example, chain can be TrustedLen and all numerical ranges can be TrustedLen. All they need to do is to report an exact size if it fits in
usize, andNoneas the upper bound otherwise.The trait describes its contract like this:
Fixes #37232