Skip to content

Commit

Permalink
Auto merge of rust-lang#11310 - y21:slow_vector_initialization_doc, r…
Browse files Browse the repository at this point in the history
…=xFrednet,djc

[`slow_vector_initialization`]: clarify why `Vec::new()` + resize is worse

rust-lang#11198 extended this lint to also warn on `Vec::new()` + `resize(0, len)`, but did not update the lint documentation, so it left some confused (rust-lang#10938 (comment)).
This PR should make it a bit more clear. (cc `@djc` `@vi` what do you think about this?)

<details>
<summary>More details</summary>

Godbolt for `Vec::new()` + `.resize(x, 0)`: https://godbolt.org/z/e7q9xc9rG

The resize call first does a normal allocation (`__rust_alloc`):
```asm
alloc::raw_vec::finish_grow:
  ...
  cmp     qword ptr [rcx + 8], 0
  je      .LBB1_7  ; if capacity == 0 -> LBB1_7

.LBB1_7:
  ...
  call    qword ptr [rip + __rust_alloc@GOTPCREL]
```

*Then* a memset for zero initialization:
```asm
example::f:
  ...
  xor     esi, esi  ; 0
  call    qword ptr [rip + memset@GOTPCREL]
```
------------

Godbolt for `vec![0; len]`: https://godbolt.org/z/M3vr53vWY

Important bit:
```asm
example::f:
  ...
  call    qword ptr [rip + __rust_alloc_zeroed@GOTPCREL]
```

</details>

changelog: [`slow_vector_initialization`]: clarify why `Vec::new()` + resize is worse than `vec![0; len]`
  • Loading branch information
bors committed Aug 9, 2023
2 parents 7c595b4 + dd25cc3 commit add2722
Showing 1 changed file with 15 additions and 5 deletions.
20 changes: 15 additions & 5 deletions clippy_lints/src/slow_vector_initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,35 @@ declare_clippy_lint! {
/// These structures are non-idiomatic and less efficient than simply using
/// `vec![0; len]`.
///
/// Specifically, for `vec![0; len]`, the compiler can use a specialized type of allocation
/// that also zero-initializes the allocated memory in the same call
/// (see: [alloc_zeroed](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#method.alloc_zeroed)).
///
/// Writing `Vec::new()` followed by `vec.resize(len, 0)` is suboptimal because,
/// while it does do the same number of allocations,
/// it involves two operations for allocating and initializing.
/// The `resize` call first allocates memory (since `Vec::new()` did not), and only *then* zero-initializes it.
///
/// ### Example
/// ```rust
/// # use core::iter::repeat;
/// # let len = 4;
/// let mut vec1 = Vec::with_capacity(len);
/// let mut vec1 = Vec::new();
/// vec1.resize(len, 0);
///
/// let mut vec1 = Vec::with_capacity(len);
/// vec1.resize(vec1.capacity(), 0);
///
/// let mut vec2 = Vec::with_capacity(len);
/// vec2.extend(repeat(0).take(len));
/// vec2.resize(len, 0);
///
/// let mut vec3 = Vec::with_capacity(len);
/// vec3.extend(repeat(0).take(len));
/// ```
///
/// Use instead:
/// ```rust
/// # let len = 4;
/// let mut vec1 = vec![0; len];
/// let mut vec2 = vec![0; len];
/// let mut vec3 = vec![0; len];
/// ```
#[clippy::version = "1.32.0"]
pub SLOW_VECTOR_INITIALIZATION,
Expand Down

0 comments on commit add2722

Please sign in to comment.