tokio-rs / bytes

Utilities for working with bytes
MIT License
1.91k stars 288 forks source link

Avoid large reallocations when freezing BytesMut #592

Closed bk2204 closed 1 year ago

bk2204 commented 1 year ago

When we freeze a BytesMut, we turn it into a Vec, and then convert that to a Bytes. Currently, this happen using Vec::into_boxed_slice, which reallocates to a slice of the same length as the Vev if the length and the capacity are not equal. This can pose a performance problem if the Vec is large or if this happens many times in a loop.

Instead, let's compare the length and capacity, and if they're the same, continue to handle this using into_boxed_slice. Otherwise, since we have a type of vtable which can handle a separate capacity, the shared vtable, let's turn our Vec into that kind of Bytes. While this does not avoid allocation altogether, it performs a fixed size allocation and avoids any need to memcpy.

Closes: #587

bk2204 commented 1 year ago

I believe I've fixed the test failure here, but will need to wait for CI to verify.

bk2204 commented 1 year ago

I've changed from using core::mem::forget to simply mem::forget, and assuming this passes CI, I think it should be ready for a final review.

bk2204 commented 1 year ago

Sure, I've added such a test. I took the liberty of also checking a length equal to the size of the capacity because I think that makes sense to test as well.