Starting with rustc 1.93, wrapping a SmallVec in any struct causes rustc to emit code that zeroes the entire struct, instead of only touching the capacity field (which was the behavior until rustc 1.92).
The larger the Array in the SmallVec, the bigger the impact. In the real world, this caused a noticeable regression in a perf test in Firefox (https://bugzilla.mozilla.org/show_bug.cgi?id=2046376)
The rustc regression itself is filed here: rust-lang/rust#157743
This can be trivially reproduced by adding the following benchmark to benches/bench.rs:
#[bench]
fn bench_new_in_newtype(b: &mut Bencher) {
struct Wrap(SmallVec<[u64; 32]>);
b.iter(|| test::black_box(Wrap(SmallVec::new())))
}
On my machine the benchmark results look like this:
|
nightly-2025-11-23 (last good) |
nightly-2025-11-24 (first bad) |
| union |
7.63ns |
10.74ns |
| non-union |
8.70ns |
13.04ns |
That is a significant overhead, and in a tight loop as in the case of Firefox, can lead to a large regression.
Starting with rustc 1.93, wrapping a SmallVec in any struct causes rustc to emit code that zeroes the entire struct, instead of only touching the capacity field (which was the behavior until rustc 1.92).
The larger the Array in the SmallVec, the bigger the impact. In the real world, this caused a noticeable regression in a perf test in Firefox (https://bugzilla.mozilla.org/show_bug.cgi?id=2046376)
The rustc regression itself is filed here: rust-lang/rust#157743
This can be trivially reproduced by adding the following benchmark to benches/bench.rs:
On my machine the benchmark results look like this:
That is a significant overhead, and in a tight loop as in the case of Firefox, can lead to a large regression.