Delegate heap from_elem construction to Vec - #9
Open
charliermarsh wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
We currently construct spilled
from_elemvalues through iterator extension. This change usesVec's fill implementation whenspecializationis disabled and transfers the allocation intoSmallVec. The existing specialized constructor is retained when that feature is enabled.The inline constructor and generic
Clonebehavior are preserved. Regression tests cover capacity boundaries, zero-sized elements, clone counts, and cleanup after a cloning panic. Stable and all-features tests, Clippy, focused Miri in both modes, and the Rust 1.86 library check pass.The committed benchmark harness is applied unchanged to the base and head for the measurements below.
Benchmarks
Performance depends on the filled value and size. Without
specialization, 64 zero-valuedu64s take 102.8–113.7% more time (+30.6–32.4 ns); nine zero bytes take 30.4–32.9% more time, and 1024 zero bytes take 18.7–20.8% more time. Nonzero byte fills improve by 52.0–53.8% at length 64 and 57.0–57.6% at length 1024; 64falsevalues improve by 65.3–65.4%.The unchanged inline length-8 constructor measures about 0.32–0.35 ns slower on stable. The unchanged stable Vec controls vary from -1.9% to +0.0% for the nonzero length-64 fill and -0.5% to +10.6% for the zero length-1024 fill, so small shifts should not be treated as demonstrated improvements.
The retained specialized constructor has substantial variation in one run: the first pair measures 64-byte fills 57.0–67.9% slower while the unchanged Vec length-64 control is 70.2% slower. Those fills range from -1.3% to +3.2% in the other two pairs, with the Vec control from -1.2% to +0.9%. All runs are included below; this shared shift limits conclusions about specialized performance.
Stable Rust 1.98.1 uses
bytes; nightly Rust 1.100.0 usesbytes,specialization. All constructors use inline capacity 8, and each timed iteration includes construction and destruction. The String case also includes creating its input string. The specialized constructor is retained; it is measured as a control alongside unchanged Vec fills.Base:
401358afromastral-sh/rust-smallvecbranchv2, with the same committed benchmark harness and dependency lockfile applied to each revision. Base and head are freshly compiled in separate target directories. AMD EPYC-Milan, x86_64 Linux, CPU 0; opt-level 3, fat LTO, one codegen unit. Criterion 0.8.2 uses 100 samples, 0.5s warmup, 2s measurement, and 95% confidence intervals. Three paired runs alternate base/head, head/base, base/head; timed processes are serialized. Before/after values below are the second pair; change ranges span all three pairs. Negative changes mean less time.from_elem/u8_19/9from_elem/u8_19/64from_elem/u8_19/1024from_elem/u8_0/9from_elem/u8_0/64from_elem/u8_0/1024from_elem/u64_0/64from_elem/bool_false/64from_elem/vec_19_control/64from_elem/vec_0_control/1024from_elem/u8_19/64from_elem/u8_0/1024from_elem/vec_19_control/64from_elem/vec_0_control/1024Full benchmark matrix
from_elem/bool_false/64from_elem/string/64from_elem/u64_0/64from_elem/u64_19/64from_elem/u8_0/1024from_elem/u8_0/64from_elem/u8_0/7from_elem/u8_0/8from_elem/u8_0/9from_elem/u8_19/1024from_elem/u8_19/64from_elem/u8_19/7from_elem/u8_19/8from_elem/u8_19/9from_elem/vec_0_control/1024from_elem/vec_19_control/64from_elem/zst/64from_elem/bool_false/64from_elem/string/64from_elem/u64_0/64from_elem/u64_19/64from_elem/u8_0/1024from_elem/u8_0/64from_elem/u8_0/7from_elem/u8_0/8from_elem/u8_0/9from_elem/u8_19/1024from_elem/u8_19/64from_elem/u8_19/7from_elem/u8_19/8from_elem/u8_19/9from_elem/vec_0_control/1024from_elem/vec_19_control/64from_elem/zst/64