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

perf: Use for_each in Vec::extend #68046

Closed
wants to merge 8 commits into from

Commits on Feb 6, 2020

  1. Add extend_chain bench

    Marwes authored and Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    ac93120 View commit details
    Browse the repository at this point in the history
  2. More chain in extend benchmark

    Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    cd551b0 View commit details
    Browse the repository at this point in the history
  3. Use a more complicated chain in benchmarks

    Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    9b0cdeb View commit details
    Browse the repository at this point in the history
  4. perf: Use for_each in Vec::extend

    `for_each` are specialized for iterators such as `chain` allowing for
    faster iteration than a normal `for/while` loop.
    
    Note that since this only checks `size_hint` once at the start it may
    end up needing to call `reserve` more in the case that `size_hint`
    returns a larger and more accurate lower bound during iteration.
    
    This could maybe be alleviated with an implementation closure like the current
    one but the extra complexity will likely end up harming the normal case
    of an accurate or 0 (think `filter`) lower bound.
    
    ```rust
    while let Some(element) = iterator.next() {
        let (lower, _) = iterator.size_hint();
        self.reserve(lower.saturating_add(1));
        unsafe {
            let len = self.len();
            ptr::write(self.get_unchecked_mut(len), element);
            // NB can't overflow since we would have had to alloc the address space
            self.set_len(len + 1);
        }
    
        iterator.by_ref().take(self.capacity()).for_each(|element| {
            unsafe {
                let len = self.len();
                ptr::write(self.get_unchecked_mut(len), element);
                // NB can't overflow since we would have had to alloc the address space
                self.set_len(len + 1);
            }
        });
    }
    
    // OR
    
    let (lower, _) = iterator.size_hint();
    self.reserve(lower);
    loop {
        let result = iterator.by_ref().try_for_each(|element| {
            if self.len() == self.capacity() {
                return Err(element);
            }
            unsafe {
                let len = self.len();
                ptr::write(self.get_unchecked_mut(len), element);
                // NB can't overflow since we would have had to alloc the address space
                self.set_len(len + 1);
            }
            Ok(())
        });
    
        match result {
            Ok(()) => break,
            Err(element) => {
                let (lower, _) = iterator.size_hint();
                self.reserve(lower.saturating_add(1));
                self.push(element);
            }
        }
    }
    ```
    
    Closes rust-lang#63340
    Marwes authored and Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    ddabd76 View commit details
    Browse the repository at this point in the history
  5. Use try_fold in Vec::extend

    Should put less stress on LLVM since there are less closures passed
    around and lets us refine how much we reserve with `size_hint` if the
    first guess is too low.
    Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    3cfa3aa View commit details
    Browse the repository at this point in the history
  6. No by_ref

    Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    824151e View commit details
    Browse the repository at this point in the history
  7. Avoid a closure in Vec::extend_desugared

    Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    a092fe1 View commit details
    Browse the repository at this point in the history
  8. Massage extend_desugared to reduce the compiletime impact

    Markus Westerlind committed Feb 6, 2020
    Configuration menu
    Copy the full SHA
    e41f55e View commit details
    Browse the repository at this point in the history