Vec::shrink_to¶
Level: reference · for working programmers
One line: Shrink the buffer, but never below the floor you name.
Stable since 1.56.0.
shrink_to(0) is exactly shrink_to_fit. Any larger argument keeps that much capacity in reserve.
Two clamps, both silent: the floor never wins against the length (capacity stays >= len(), so shrink_to(2) on a vector of length 5 leaves at least 5), and a floor above the current capacity does nothing at all — it never grows the buffer. Use reserve for that.
The shape it exists for is a reused buffer that occasionally spikes. A parser that reads mostly small records and one enormous one should hand the enormous allocation back without dropping to zero and reallocating on the next small record. shrink_to_fit in that loop reallocates every round; shrink_to(64) reallocates only after the spike.
Example¶
vec_shrink_to.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
// Shrink, but not below the floor you name.
let mut v: Vec<u32> = Vec::with_capacity(100);
v.extend_from_slice(&[1, 2, 3]);
v.shrink_to(10);
println!("len {} cap {}", v.len(), v.capacity());
// The floor never wins against the length: capacity stays >= len.
let mut v = vec![1u32, 2, 3, 4, 5];
v.shrink_to(2);
println!("asked for 2 with len 5: cap {}", v.capacity());
// A floor above the current capacity does nothing — it never grows.
let mut v: Vec<u8> = Vec::with_capacity(4);
v.shrink_to(100);
println!("shrink_to(100) on cap 4: cap {}", v.capacity());
// shrink_to(0) is shrink_to_fit().
let mut a: Vec<u16> = Vec::with_capacity(50);
a.push(1);
let mut b = a.clone();
a.shrink_to(0);
b.shrink_to_fit();
println!("shrink_to(0) {} == shrink_to_fit {}", a.capacity(), b.capacity());
// Where the floor earns its keep: a reused buffer that should give memory
// back after a spike, but keep enough for the ordinary case.
let mut buf: Vec<u8> = Vec::new();
let mut caps = vec![];
for size in [4, 4096, 4, 4] {
buf.clear();
buf.resize(size, 0);
buf.shrink_to(64); // never below 64, never hoard 4 KiB
caps.push(buf.capacity());
}
println!("capacity across a spike: {caps:?}");
// Same thing with shrink_to_fit would reallocate back up every round.
let mut buf: Vec<u8> = Vec::new();
let mut caps = vec![];
for size in [4, 4096, 4, 4] {
buf.clear();
buf.resize(size, 0);
buf.shrink_to_fit();
caps.push(buf.capacity());
}
println!("with shrink_to_fit: {caps:?}");
}
Verified output of vec_shrink_to.rs — regenerated by tools/run_examples.py, never hand-typed.
len 3 cap 10
asked for 2 with len 5: cap 5
shrink_to(100) on cap 4: cap 4
shrink_to(0) 1 == shrink_to_fit 1
capacity across a spike: [8, 4096, 64, 64]
with shrink_to_fit: [4, 4096, 4, 4]
See also¶
Vec::shrink_to_fit— the floorless versionVec::clear— the other half of the reuse loopVec::capacity— the number this changes