-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add slice::fill #70752
Add slice::fill #70752
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @rust-lang/libs
This seems like a reasonable abstraction to add as outlined by @bluss in rust-lang/rfcs#2067 (comment) towards which there didn't seem to be much disagreement at the time.
There are some small adjustments that are necessary (and you'll need to run ./x.py fmt
locally as well, please squash those commits into the first one), but this looks good overall.
As this only adds an unstable method, r=me with these comments addressed.
r? @Centril |
Should this take the fill value by reference since it's cloning it into each position? Alternatively it could tweak the logic a bit to move the value into the last position, but that might just mess it up optimization wise. |
@sfackler oh I like your first suggestion a lot. I just tested this using the pub fn run_u8(buf: &mut Vec<u8>) {
buf.fill(&1);
buf.fill(1);
} I think that should guarantee the value doesn't need to be consumed, but can also just be passed if desired. I'll go ahead and update the patch to include the |
@bors r+ rollup Thanks! |
📌 Commit 2af9adc694ed0f8b46014d61b3020c1e9a55130b has been approved by |
🌲 The tree is currently closed for pull requests below priority 1000, this pull request will be tested once the tree is reopened |
Updated with the suggestion from @ollie27 in #70752 (comment) which may reduce resource usage in certain cases. |
@bors r+ |
📌 Commit edabceb has been approved by |
Rollup of 6 pull requests Successful merges: - rust-lang#70635 (rustc_target: Some cleanup to `no_default_libraries`) - rust-lang#70748 (Do not disable field reordering on enums with big discriminant) - rust-lang#70752 (Add slice::fill) - rust-lang#70766 (use ManuallyDrop instead of forget inside collections) - rust-lang#70768 (macro_rules: `NtLifetime` cannot start with an identifier) - rust-lang#70783 (comment refers to removed type) Failed merges: r? @ghost
Adds the
slice::fill
method to fill a slice with an item. This replaces manual for loops where items are copied one-by-one. This is a counterpart to C++20'sstd::fill
function.Usage
Performance
When compiling in release mode, for
[u8]
and[u16]
this method will optimize to amemset(3)
call (godbolt). The initial implementation relies on LLVM's optimizer to make it as fast as possible for any given input. But as @jonas-schievink pointed out this can later be optimized through specialization to guarantee it has a specific performance profile.Why now?
Conversations about adding
slice::fill
are not new. In fact, rust-lang/rfcs#2067 was opened 3 years ago about this exact topic. However discussion stranded while discussing implementation details, and it's not seen much forward motion since.In "The Hunt for the Fastest Zero" Travis Downs provides disects C++'s
std::fill
performance profile on gcc, comparing it among others tomemset(3)
. Even thoughmemset(3)
outperformsstd::fill
in their tests, the author notes the following:Much of the article focuses on how how to fix the performance of
std::fill
by providing specializations for specific input. In Rust we don't have any dedicated methods to fill slices with values, so it either needs to be optimized at the MIR layer, or more likely rely on LLVM's optimizer.By adding a dedicated method for filling slices with values it opens up the ability for us to in the future guarantee that e.g.
Vec<u8>
will always optimize tomemset
even in debug mode. Or perhaps provide stronger guarantees about memory when zeroing values when a certain flag is passed. But regardless of that, it improves general ergonomics of working with slices by providing a dedicated method with documentation and examples.References