Description
The behaviour of the .reserve_at_least
is much better asymptotically, since calling .reserve
in a loop will cause quadratic behaviour. We should be using the short method name to encourage the faster behaviour.
.reserve(n)
allocates exactly enough capacity to store n
elements (if there isn't enough space already), while .reserve_at_least(n)
will ensure that there is enough space, but overallocate to ensure that reallocations don't occur too often (i.e. increase the allocation size exponentially).
e.g. imagine a protocol which consists of a sets of messages, where set block as an initial message with the count for that set:
let received = ~[];
let mut total_messages = 0;
while listener.more_messages() {
let next_count = listener.recv();
total_messages += next_count;
// we know how many we're going to have total, so
// might as well allocate it up-front.
received.reserve(total_messages);
for _ in range(0, next_count) {
received.push(listener.recv());
}
}
using (the current) .reserve
causes every single set to do a reallocation and memcpy
(i.e. O(n^2) behaviour), while using .reserve_at_least
would mean the reallocation and memcpy only happens logarithmically often, preserving O(n) asymptotics.
(For vector specifically the above should really be using .reserve_additional
, but other types like ~str
and extra::{priority_queue, ring_buf}
suffer the same problem.)