Skip to content

Commit

Permalink
Rollup merge of rust-lang#128234 - jcsp:retain-empty-case, r=tgross35
Browse files Browse the repository at this point in the history
Optimize empty case in Vec::retain

While profiling some code that happens to call Vec::retain() in a tight loop, I noticed more runtime than expected in retain, even in a bench case where the vector was always empty.  When I wrapped my call to retain in `if !myvec.is_empty()` I saw faster execution compared with doing retain on an empty vector.

On closer inspection, Vec::retain is doing set_len(0) on itself even when the vector is empty, and then resetting the length again in BackshiftOnDrop::drop.

Unscientific screengrab of a flamegraph illustrating how we end up spending time in set_len and drop:
![image](https://github.com/user-attachments/assets/ebc72ace-84a0-4432-9b6f-1b3c96d353ba)
  • Loading branch information
matthiaskrgr authored Jul 29, 2024
2 parents 552017a + 6a6824a commit e828303
Showing 1 changed file with 6 additions and 0 deletions.
6 changes: 6 additions & 0 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1710,6 +1710,12 @@ impl<T, A: Allocator> Vec<T, A> {
F: FnMut(&mut T) -> bool,
{
let original_len = self.len();

if original_len == 0 {
// Empty case: explicit return allows better optimization, vs letting compiler infer it
return;
}

// Avoid double drop if the drop guard is not executed,
// since we may make some holes during the process.
unsafe { self.set_len(0) };
Expand Down

0 comments on commit e828303

Please sign in to comment.