#`BytesMut` capacity reclaiming behavior

15 messages · Page 1 of 1 (latest)

spark minnow
#

I have a long-lived BytesMut buffer that I use for encoding messages before sending them over a socket. The flow is something like:

let mut buf = BytesMut::with_capacity(…);
let mut socket: impl Sink;

loop {
    { // this step may happen 0.. times during any given iteration
        let msg: CustomMessageType = todo!();
        encode(&msg, &mut buf);
        socket.feed(buf.split()).await?;
    }

    socket.flush().await?;
}

Can I assume that the BytesMut will re-use the same allocation over and over again? As far as I understand, as long as all feed calls combined don't exceed the original capacity, it should be able to reclaim the old space?

tender lichen
#

Given the use of flush, it would be assumed that all refs will have been dropped so that buf is the sole owner. But it won't reclaim unless it needs more capacity. It might only get to that point half way through your loop, where there's already a bunch of shared refs around which makes the reclaim fail

spark minnow
# tender lichen Given the use of flush, it would be assumed that all refs will have been dropped...

Why would reclaiming at the start of the loop change anything, then? If it needs more space somewhere in the middle of the feed calls, it has to re-allocate, sure. But not at the first call to feed (in any given iteration), right? My thought process is that: if the buffer is full at the start of an iteration, the next call to feed (or encode rather) should attempt to grow the buffer, which should attempt to reclaim old space. Because of the flush, at that point there should be no outstanding references anymore, so the reclaim should succeed. Now, if at any point we need more space than the original capacity, it needs to grow (which is fine). But as long as that doesn't happen...?

tender lichen
#

So it's best to reclaim the full buffer when you know it should be free

tender lichen
#

But maybe use try_reclaim incase the assumption is wrong I suppose

spark minnow
#

hmm, but how do I know how much to reclaim? try_reclaim wants an additional parameter, which would be the difference between the original capacity and the current one? but if it grows at any point, I lose track of the full capacity

tender lichen
#

additional is based on current length (eg 0)

spark minnow
tender lichen
spark minnow
#

so saving the initial capacity outside the loop and try_reclaiming that at the start of each iteration should be sufficient?

tender lichen
#

Yeah, I imagine so.