Uh oh!
There was an error while loading. Please reload this page.
Add Extend::{extend_one,extend_reserve} - #72162
Conversation
rust-highfive
commented
May 13, 2020
(rust_highfive has picked a reviewer for you, use r? to override) |
cuviper
commented
May 13, 2020
This was developed from the discussion on #72085, overlapping but independent of #72159. I showed that it achieved similar performance to an imperative |
Dylan-DPC-zz
commented
May 20, 2020
r? @dtolnay |
This comment has been minimized.
This comment has been minimized.
Mark-Simulacrum
commented
May 21, 2020
Bikeshed: push instead of extend_one? Are we using size hints already to pre-reserve? I would've expected an extend(Some(foo)) to basically compile down to a push - if that doesn't happen today, perhaps worth investigating? I think the only reason we have the somewhat awkward method names is also because Extend is im the prelude, right? So we don't want to use e.g. push and reserve? |
cuviper
commented
May 21, 2020
There's no way to do that in
Here's a playground of the benchmarks from #72085, and my local results: Note that Looking at the assembly, the biggest difference I see is that That's particular to
Yeah, I think being in the prelude warrants caution in method ambiguity. |
Mark-Simulacrum
commented
May 21, 2020
I meant reserving in the Extend impls - those have an iterator to work with, so I would've expected it to be feasible there. But if there's an unconditional reserve already then maybe that is covered. I want to take a closer look at the diff, but I think in principle this is reasonable, so I'll probably approve it (we can bikeshed names on a tracking issue). |
cuviper
commented
May 21, 2020
Oh sure, in general, collections will reserve space in |
Mark-Simulacrum
commented
May 26, 2020
Okay, I haven't found the time to do the investigation myself I wanted to, but this seems like a good change regardless. Given the amount of code using extend (and zip etc) which is affected by this, I would like to @bors try @rust-timer queue though just to make sure we're not unduly generating more LLVM IR or something like that causing compile times to increase. Also, can someone on @rust-lang/libs sign off on adding these APIs (unstable for now)? Presuming we get a go-ahead can you file a tracking issue, @cuviper and update the attributes? |
rust-timer
commented
May 26, 2020
Awaiting bors try build completion |
bors
commented
May 26, 2020
⌛ Trying commit 36b7b8ee5ce9321f60e21c60f2f85d76cd0b1a0a with merge d448c21d56eddbda45277b26ed4f17faf4c5db3c... |
dtolnay
left a comment
There was a problem hiding this comment.
Looks good to me to land unstable but I haven't gotten to review the whole PR yet, only collect.rs.
Uh oh!
There was an error while loading. Please reload this page.
Mark-Simulacrum
left a comment
There was a problem hiding this comment.
r=me with tracking issue assigned
Implementation looks good to me, at least for an initial draft.
Uh oh!
There was an error while loading. Please reload this page.
SimonSapin
commented
May 26, 2020
These methods look very out of place in the From an API design perspective, this seems to be asking for new |
cuviper
commented
May 26, 2020
@SimonSapin for the goal of improving |
Mark-Simulacrum
commented
May 26, 2020
I agree that they feel a bit out of place, although they do relatively naturally coincide with extending IMO. I don't think separate traits make a lot of sense, unfortunately, because we lack specialization (and aren't getting it anytime soon I imagine in flexible enough form). You really want to be able to call e.g. push and have that fallback to just extending if there's no separate push implementation defined. I would, though, be fine saying that these are internal methods not currently on a (clear) path to stabilization (and perhaps marking them as doc(hidden)). |
cuviper
commented
May 26, 2020
I've made the requested changes and filed tracking issue #72631. I guess we should at least wait for that perf run before merging though.
It would be a wart of its own to put third-party collections at a disadvantage. There's nothing technically special here to warrant permanent unstability, versus actual specialization. I think this is a relatively mild API choice, just with a bit of historical baggage that |
cuviper
commented
May 27, 2020
I'll see if I can reproduce the max-rss locally and track that down. Most of those The one hunch I have is with I guess it could also be that the new methods just mean more code, but I wouldn't think |
cuviper
commented
May 27, 2020
I blame jemalloc for the RSS variability, and I don't think my change really affected it. Here are my results on the worst in that report,
(measuring |
Mark-Simulacrum
commented
May 27, 2020
Hm, I wonder if we can configure jemalloc to be less variable or perhaps disable it on rust-timer entirely. cc @eddyb / @nnethercote Regardless seems like perf is fine -- @bors r+ I think we can discuss @SimonSapin's concern (#72162 (comment)) more on the tracking issue if the responses to the original comment didn't resolve it, given that this is just adding some unstable functionality and can easily be reverted if needed. |
bors
commented
May 27, 2020
📌 Commit 02226e0 has been approved by |
nnethercote
commented
May 27, 2020
To understand the memory impact of changes I strongly recommend using either Massif or DHAT, if you are on Linux. Basic docs are here. If you try DHAT you need to look at the |
cuviper
commented
May 28, 2020
@nnethercote I just compiled |
nnethercote
commented
May 28, 2020
@cuviper: that's a very strong indication that it's just noise, then. Indeed, https://perf.rust-lang.org/?start=&end=&absolute=true&stat=max-rss shows that keccak's max-rss numbers are extremely noisy. |
Add Extend::{extend_one,extend_reserve}
This adds new optional methods on `Extend`: `extend_one` add a single
element to the collection, and `extend_reserve` pre-allocates space for
the predicted number of incoming elements. These are used in `Iterator`
for `partition` and `unzip` as they shuffle elements one-at-a-time into
their respective collections.Add Extend::{extend_one,extend_reserve}
This adds new optional methods on `Extend`: `extend_one` add a single
element to the collection, and `extend_reserve` pre-allocates space for
the predicted number of incoming elements. These are used in `Iterator`
for `partition` and `unzip` as they shuffle elements one-at-a-time into
their respective collections.RalfJung
commented
May 29, 2020
@bors r- |
This adds new optional methods on `Extend`: `extend_one` add a single element to the collection, and `extend_reserve` pre-allocates space for the predicted number of incoming elements. These are used in `Iterator` for `partition` and `unzip` as they shuffle elements one-at-a-time into their respective collections.
Co-authored-by: David Tolnay <dtolnay@gmail.com>
cuviper
commented
May 30, 2020
Rebased. @bors r=Mark-Simulacrum |
bors
commented
May 30, 2020
📌 Commit a51b22a has been approved by |
Rollup of 10 pull requests Successful merges: - rust-lang#72033 (Update RELEASES.md for 1.44.0) - rust-lang#72162 (Add Extend::{extend_one,extend_reserve}) - rust-lang#72419 (Miri read_discriminant: return a scalar instead of raw underlying bytes) - rust-lang#72621 (Don't bail out of trait selection when predicate references an error) - rust-lang#72677 (Fix diagnostics for `@ ..` binding pattern in tuples and tuple structs) - rust-lang#72710 (Add test to make sure -Wunused-crate-dependencies works with tests) - rust-lang#72724 (Revert recursive `TokenKind::Interpolated` expansion for now) - rust-lang#72741 (Remove unused mut from long-linker-command-lines test) - rust-lang#72750 (Remove remaining calls to `as_local_node_id`) - rust-lang#72752 (remove mk_bool) Failed merges: r? @ghost
This adds new optional methods on
Extend:extend_oneadd a singleelement to the collection, and
extend_reservepre-allocates space forthe predicted number of incoming elements. These are used in
Iteratorfor
partitionandunzipas they shuffle elements one-at-a-time intotheir respective collections.