peterulb
peterulb

Reputation: 2988

How to shrink a Vec or String from an offset without reallocating it?

Multiple structures in rust have shrink_to or shrink_to_fit methods, such as Vec and String. But apparently there's nothing like shrink_from_to.

Why would I want that?

Assume I've a XY gigabyte string or vector in memory and know the exact start and end positions of the part I am interesting in (which allocates only Z GB from start to end, somewhere in the middle). I could call truncate and then shrink_from_to effectivly freeing memory.
However I've still gigabytes of memory occupied by [0..start] which are of no relevance for my further processing.

Question

Is there any way to free this memory too without reallocating and copying the relevant parts there?

Upvotes: 0

Views: 808

Answers (2)

Masklinn
Masklinn

Reputation: 42272

Is there any way to free this memory too without reallocating and copying the relevant parts there?

Move the segment you want to keep to the start of the collection (e.g. replace_range, drain, copy_within, rotate, ...), then truncate, then shrink.

APIs like realloc and mremap work in terms of "memory blocks" (aka allocations returned by malloc/mmap), they don't work in terms of random pointers. So a hypothetical shrink_from_to would just be doing that under the cover, since you can't really resize allocations from both ends.

Upvotes: 1

BallpointBen
BallpointBen

Reputation: 13750

Note that shrink_to_fit does reallocate by copying into a smaller buffer and freeing the old buffer. Your best bet is probably just converting the slice you care about into an owned Vec and then dropping the original Vec.

fn main() {
    let v1 = (0..1000).collect::<Vec<_>>(); // needs to be dropped
    println!("{}", v1.capacity()); // 1000
    let v2 = v1[100..150].to_owned(); // don't drop this!
    println!("{}", v2.capacity()); // 50
    drop(v1);
}

Upvotes: 1

Related Questions