O(1) time {Vec,VecDeque}::truncate for trivial drop types and VecDeque::truncate_front #62408
Labels
C-enhancement
Category: An issue proposing an enhancement or a PR with one.
C-optimization
Category: An issue highlighting optimization opportunities or PRs implementing such
I-slow
Issue: Problems and improvements with respect to performance of generated code.
T-libs-api
Relevant to the library API team, which will review and decide on the PR/issue.
Currently both
Vec
s andVecDeque
struncate
implementations just callpop_back()
in a loop. Whenstd::mem::needs_drop::<T>()
isfalse
this is pretty inefficient.Now LLVM does optimize away the loop on
-O3
forVec::truncate
, however this does not happen forVecDeque::truncate
.Despite previous complaints, this exact issue has been wont-fix'd under the unofficial policy that we do not include -O0 exclusive optimizations in rust.
I would like to re-open the discussion with the following observations, in the hope that @alexcrichton might change his mind:
No matter the optimization level, the optimization never happens for
VecDeque::truncate
.The optimization is not just a constant factor speedup, it's an asymptotic speedup changing an O(n) time operation into O(1) where O(1) could easily be guaranteed. The difference in speed could literally be several orders of magnitude.
The optimizer is always fickle and ever-changing. Someone designing an algorithm using default Rust building blocks needs to rely on at least asymptotic complexities not suddenly regressing due to the optimizer not catching some pattern. Updating your Rust compiler should never have a chance to turn an O(n) algorithm into an O(n^2) one.
It pushes people towards unsafe code. In the linked complaint above the user ended up using the unsafe
set_len
when the safetruncate
could've exactly done the job.In addition to the above,
VecDeque
hastruncate
, but is missingtruncate_front
. If we make these truncate operations O(1) time it should also get atruncate_front
operation.Without these changes it is impossible to implement certain algorithms using the default Rust collections for no particular good reason. For example, if I have a
v: VecDeque<f64>
that keeps its elements sorted, it is currently impossible to write a O(log n) time routine that removes all elements less thanx
inv
. We can find how many elements we need to remove from the front in O(log n) time, but removing them needlessly take O(n) time.The text was updated successfully, but these errors were encountered: