Skip to content

impl FromIterator for BytesMut exposes implementation details #723

Open
@aatifsyed

Description

@aatifsyed

BytesMut cares about keeping allocation implementation details private, which means no From<Vec<u8>> and no Into<Vec<u8>>:

bytes/src/bytes_mut.rs

Lines 825 to 830 in 4e2c9c0

// For now, use a `Vec` to manage the memory for us, but we may want to
// change that in the future to some alternate allocator strategy.
//
// Thus, we don't expose an easy way to construct from a `Vec` since an
// internal change could make a simple pattern (`BytesMut::from(vec)`)
// suddenly a lot more expensive.

However, this information is leaked in the FromIterator impl:

bytes/src/bytes_mut.rs

Lines 1409 to 1413 in f8c7b57

impl FromIterator<u8> for BytesMut {
fn from_iter<T: IntoIterator<Item = u8>>(into_iter: T) -> Self {
BytesMut::from_vec(Vec::from_iter(into_iter))
}
}

which go through through this specialization:
https://github.com/rust-lang/rust/blob/6c6b3027ef62e911142cfc55589baef4e9f38ec8/library/alloc/src/vec/spec_from_iter.rs#L37-L64

So collection is basically a From<Vec<u8>> with no overhead, which may not be intended by the authors.

use bytes::BytesMut; // 1.6.1

#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc; // 0.3.3

fn main() {
    let _guard = dhat::Profiler::new_heap();

    let src = vec![1; 1024];
    let mut_from_vec = measure(|| BytesMut::from_iter(src));
    assert_eq!(mut_from_vec, 0); // doesn't allocate!

    let mut_from_array = measure(|| BytesMut::from_iter([1; 1024]));
    assert_eq!(mut_from_array, 1024);
}

fn measure<T>(f: impl FnOnce() -> T) -> u64 {
    let before = dhat::HeapStats::get();
    f();
    let after = dhat::HeapStats::get();
    after.total_bytes - before.total_bytes
}

OTOH, this probably doesn't count as "an easy way", so maybe it's fine to leave it exposed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions