I am currently working on a library that copies a data slice received from a QUIC library into a passed in buffer. I didn't want to force a specific buffer type so I have the passed in buffer implement for<'a> Extend<&'a u8>. Currently if a Vec is passed in as the buffer it compiles down to a memcpy. This makes sense because Vec's docs state:
This implementation is specialized for slice iterators, where it uses copy_from_slice to append the entire slice at once.
Meanwhile BytesMut copies data byte-by-byte, even when compiled in release mode.
Here's a playground link with the following source code to verify that BytesMut copies data byte-by-byte:
use bytes::{Bytes, BytesMut};
#[inline(always)]
fn read_into_buf(bytes_from_network: &[u8], buf: &mut impl for<'a> Extend<&'a u8>) -> () {
buf.extend(bytes_from_network);
}
#[unsafe(no_mangle)]
fn with_vec(bytes_from_network: &[u8]) {
let mut into = Vec::new();
read_into_buf(bytes_from_network, &mut into);
}
#[unsafe(no_mangle)]
fn with_bytes_mut(bytes_from_network: &[u8]) {
let mut into = BytesMut::new();
read_into_buf(bytes_from_network, &mut into);
}
The BytesMut Extend implementation currently has this as a TODO comment:
|
// TODO: optimize |
|
// 1. If self.kind() == KIND_VEC, use Vec::extend |
|
for b in iter { |
|
self.put_u8(b); |
|
} |
I was wondering if there was a reason this optimization has not been implemented yet. It would allow extend calls, like the one in my library, to turn into memcpy instead of copying data byte-by-byte.
I am currently working on a library that copies a data slice received from a QUIC library into a passed in buffer. I didn't want to force a specific buffer type so I have the passed in buffer implement
for<'a> Extend<&'a u8>. Currently if aVecis passed in as the buffer it compiles down to amemcpy. This makes sense becauseVec's docs state:Meanwhile
BytesMutcopies data byte-by-byte, even when compiled in release mode.Here's a playground link with the following source code to verify that
BytesMutcopies data byte-by-byte:The BytesMut Extend implementation currently has this as a TODO comment:
bytes/src/bytes_mut.rs
Lines 1494 to 1498 in 7930d93
I was wondering if there was a reason this optimization has not been implemented yet. It would allow
extendcalls, like the one in my library, to turn intomemcpyinstead of copying data byte-by-byte.