Description
VecDeque
currently allocates one extra empty element because it needs to discern between an empty and full queue. Besides wasting memory, this means VecDeque::new
cannot currently be const
.
Solution
The most elegant solution would be to reimplement VecDeque
based off the (third) technique described by Juho Snellman in this blog post. In this implementation, the buffer indexes are not clamped to the buffer size, but instead use the whole range of usize
. Only when accessing an element are they masked to fit. The length of the buffer is defined by the wrapping distance between the two indexes. By limiting the capacity to values smaller than isize::MAX
(which Rust's memory model dictates anyway), an empty queue (with head == tail
) is strictly different from a full queue (where head - tail == capacity
).
In the described implementation, the capacity is always be a power of two so that wrapping arithmetic can be used. This is great for performance and simplifies the implementation, but may result in significant unused memory when a large but precise capacity is required. Therefore, Eli Dupree proposed a variation where the indexes are kept smaller than 2 * capacity
using modular arithmetic, which would relax the above requirement but incur higher runtime cost since the more expensive modular arithmetic needs to be used.
Links and related work
- Previous discussion on Rust Internals
@rustbot label +T-libs +T-libs-api