Repository navigation
When collecting into a Vec, don't reserve extra room if we have a size_hint upper bound - #163846
joshtriplett wants to merge 1 commit into
Conversation
…e_hint upper bound Vec currently forces a minimum number of elements for small vectors (minimum 4 for most object sizes). This results in wasted capacity for small vectors, when collecting from an iterator with a known size of 1, 2, or 3. Vec already effectively does this when collecting from an iterator with TrustedLen, but doesn't for other iterators. Try the experiment of doing so for any iterator whose size_hint has a matching lower and upper bound (iterators that know their exact size). Found via performance analysis that turned up a missing TrustedLen resulting in missing this optimization. Credit to Josh Stone for the idea of doing this for *every* collect rather than just those on TrustedLen.
|
r? @clarfonthey rustbot has assigned @clarfonthey. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
When collecting into a Vec, don't reserve extra room if we have a size_hint upper bound
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (4d57bc6): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never rustc-perf Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -0.9%, secondary -2.6%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary -0.2%, secondary 5.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary -0.1%, secondary 0.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 496.563s -> 489.622s (-1.40%) |
|
We can do this on every push, but not sure if this will be beneficial. |
|
I think with this kind of lukewarm perf I would probably only be happy if it simplified the resulting logic, but that's not the case here. Would be happy to be proven wrong with other benchmarks, though; the compiler isn't the only thing using |
|
(waiting on author could mean waiting on more benchmarks/justification, or code changes, but I don't think I'd be happy merging this as-is given just the existing perf run) |
|
I don't think this will improve performance, at most memory usage. |
Right. My hope here is, roughly, "performance neutral but saves memory". |
|
Okay, I reread and now that feels a bit more clear. Unfortunately, we won't be able to detect this in the compiler since it generally allocates small vectors on the stack. I do wonder if there'd be a better way to test the impact of this. Memory is historically a very noisy metric. |
It's possible to get a better idea locally by running with DHAT or heaptrack. |
Vec currently forces a minimum number of elements for small vectors
(minimum 4 for most object sizes). This results in wasted capacity for
small vectors, when collecting from an iterator with a known size of 1,
2, or 3.
Vec already effectively does this when collecting from an iterator with
TrustedLen, but doesn't for other iterators.
Try the experiment of doing so for any iterator whose size_hint has a
matching lower and upper bound (iterators that know their exact size).
Found via performance analysis that turned up a missing TrustedLen
resulting in missing this optimization. Credit to Josh Stone for the
idea of doing this for every collect rather than just those on
TrustedLen.