Avoid SmallVec::collect() in Result::intern_with().

This commit reduces instruction counts for several benchmarks by up to
5%.
This commit is contained in:
Nicholas Nethercote 2019-10-01 11:57:36 +10:00
parent 14192607d3
commit 1937c200cd

View file

@ -2848,8 +2848,29 @@ impl<'a, T, R> InternIteratorElement<T, R> for &'a T
impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
type Output = Result<R, E>;
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
Ok(f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?))
fn intern_with<I: Iterator<Item=Self>, F: FnOnce(&[T]) -> R>(mut iter: I, f: F)
-> Self::Output {
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// The match arms are in order of frequency. The 1, 2, and 0 cases are
// typically hit in ~95% of cases. We assume that if the upper and
// lower bounds from `size_hint` agree they are correct.
Ok(match iter.size_hint() {
(1, Some(1)) => {
f(&[iter.next().unwrap()?])
}
(2, Some(2)) => {
let t0 = iter.next().unwrap()?;
let t1 = iter.next().unwrap()?;
f(&[t0, t1])
}
(0, Some(0)) => {
f(&[])
}
_ => {
f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?)
}
})
}
}