The `is_unique` entry in the vtable for `Bytes` created from a shared
`BytesMut` just called the `shared_is_unique` function from the `bytes`
module. However, that function dereferences the `data` argument` as
`bytes::Shared`, but the actual underlying type is `bytes_mut::Shared`.
<Arc<T>>::make_mut returns a &mut T, such an API is doable for Bytes too
and thus we should reserve Bytes::make_mut for that.
Furthermore, it would be helpful to use From<Bytes> as a trait bound
in some cases with other traits such as Hyper's body trait, where Hyper
gives you Bytes values.
Finally, making it impl From<Bytes> for BytesMut means the API is more
easily discoverable as it appears on both Bytes and BytesMut.
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.
Fixes calls to `reserve` when the underlying shared buffer was already
big enough to fit the requested capacity. Previously a new even larger
buffer was created anyways. This could eventually lead to an OOM
condition.
* Optimize `BytesMut::reserve`: Reuse vec if possible
If the `BytesMut` holds a unqiue reference to `KIND_ARC` while the
capacity of the `Vec` is not big enough , reuse the existing `Vec`
instead of allocating a new one.
Signed-off-by: Jiahao XU <[email protected]>
Rewrote the ledger in test_bytes_vec_alloc.rs to not piss off miri. The ledger is now a table within the allocator, which seems to satisfy miri. The old solution was to bundle an extra usize into the beginning of each allocation and then index past the start when deallocating data to get the size.