From 01ae379526218e7f6ca28510b6c06098419b7380 Mon Sep 17 00:00:00 2001 From: Chih-Hung Hsieh Date: Wed, 10 Jun 2020 20:15:59 -0700 Subject: Import bytes-0.5.4 * Add OWNERS and Android.bp Bug: 143953733 Test: make Change-Id: Ica69d7252abb1c2967f2c0e11a62d0bd83192fb3 --- benches/buf.rs | 187 ++++++++++++++++++++++++++++++++++++++ benches/bytes.rs | 118 ++++++++++++++++++++++++ benches/bytes_mut.rs | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 554 insertions(+) create mode 100644 benches/buf.rs create mode 100644 benches/bytes.rs create mode 100644 benches/bytes_mut.rs (limited to 'benches') diff --git a/benches/buf.rs b/benches/buf.rs new file mode 100644 index 0000000..0c9a1d9 --- /dev/null +++ b/benches/buf.rs @@ -0,0 +1,187 @@ +#![feature(test)] +#![deny(warnings, rust_2018_idioms)] + +extern crate test; + +use test::Bencher; +use bytes::Buf; + +/// Dummy Buf implementation +struct TestBuf { + buf: &'static [u8], + readlens: &'static [usize], + init_pos: usize, + pos: usize, + readlen_pos: usize, + readlen: usize, +} +impl TestBuf { + fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBuf { + let mut buf = TestBuf { + buf, + readlens, + init_pos, + pos: 0, + readlen_pos: 0, + readlen: 0, + }; + buf.reset(); + buf + } + fn reset(&mut self) { + self.pos = self.init_pos; + self.readlen_pos = 0; + self.next_readlen(); + } + /// Compute the length of the next read : + /// - use the next value specified in readlens (capped by remaining) if any + /// - else the remaining + fn next_readlen(&mut self) { + self.readlen = self.buf.len() - self.pos; + if let Some(readlen) = self.readlens.get(self.readlen_pos) { + self.readlen = std::cmp::min(self.readlen, *readlen); + self.readlen_pos += 1; + } + } +} +impl Buf for TestBuf { + fn remaining(&self) -> usize { + return self.buf.len() - self.pos; + } + fn advance(&mut self, cnt: usize) { + self.pos += cnt; + assert!(self.pos <= self.buf.len()); + self.next_readlen(); + } + fn bytes(&self) -> &[u8] { + if self.readlen == 0 { + Default::default() + } else { + &self.buf[self.pos..self.pos + self.readlen] + } + } +} + +/// Dummy Buf implementation +/// version with methods forced to not be inlined (to simulate costly calls) +struct TestBufC { + inner: TestBuf, +} +impl TestBufC { + fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBufC { + TestBufC { + inner: TestBuf::new(buf, readlens, init_pos), + } + } + fn reset(&mut self) { + self.inner.reset() + } +} +impl Buf for TestBufC { + #[inline(never)] + fn remaining(&self) -> usize { + self.inner.remaining() + } + #[inline(never)] + fn advance(&mut self, cnt: usize) { + self.inner.advance(cnt) + } + #[inline(never)] + fn bytes(&self) -> &[u8] { + self.inner.bytes() + } +} + +macro_rules! bench { + ($fname:ident, testbuf $testbuf:ident $readlens:expr, $method:ident $(,$arg:expr)*) => ( + #[bench] + fn $fname(b: &mut Bencher) { + let mut bufs = [ + $testbuf::new(&[1u8; 8+0], $readlens, 0), + $testbuf::new(&[1u8; 8+1], $readlens, 1), + $testbuf::new(&[1u8; 8+2], $readlens, 2), + $testbuf::new(&[1u8; 8+3], $readlens, 3), + $testbuf::new(&[1u8; 8+4], $readlens, 4), + $testbuf::new(&[1u8; 8+5], $readlens, 5), + $testbuf::new(&[1u8; 8+6], $readlens, 6), + $testbuf::new(&[1u8; 8+7], $readlens, 7), + ]; + b.iter(|| { + for i in 0..8 { + bufs[i].reset(); + let buf: &mut dyn Buf = &mut bufs[i]; // type erasure + test::black_box(buf.$method($($arg,)*)); + } + }) + } + ); + ($fname:ident, slice, $method:ident $(,$arg:expr)*) => ( + #[bench] + fn $fname(b: &mut Bencher) { + // buf must be long enough for one read of 8 bytes starting at pos 7 + let arr = [1u8; 8+7]; + b.iter(|| { + for i in 0..8 { + let mut buf = &arr[i..]; + let buf = &mut buf as &mut dyn Buf; // type erasure + test::black_box(buf.$method($($arg,)*)); + } + }) + } + ); + ($fname:ident, option) => ( + #[bench] + fn $fname(b: &mut Bencher) { + let data = [1u8; 1]; + b.iter(|| { + for _ in 0..8 { + let mut buf = Some(data); + let buf = &mut buf as &mut dyn Buf; // type erasure + test::black_box(buf.get_u8()); + } + }) + } + ); +} + +macro_rules! bench_group { + ($method:ident $(,$arg:expr)*) => ( + bench!(slice, slice, $method $(,$arg)*); + bench!(tbuf_1, testbuf TestBuf &[], $method $(,$arg)*); + bench!(tbuf_1_costly, testbuf TestBufC &[], $method $(,$arg)*); + bench!(tbuf_2, testbuf TestBuf &[1], $method $(,$arg)*); + bench!(tbuf_2_costly, testbuf TestBufC &[1], $method $(,$arg)*); + // bench!(tbuf_onebyone, testbuf TestBuf &[1,1,1,1,1,1,1,1], $method $(,$arg)*); + // bench!(tbuf_onebyone_costly, testbuf TestBufC &[1,1,1,1,1,1,1,1], $method $(,$arg)*); + ); +} + +mod get_u8 { + use super::*; + bench_group!(get_u8); + bench!(option, option); +} +mod get_u16 { + use super::*; + bench_group!(get_u16); +} +mod get_u32 { + use super::*; + bench_group!(get_u32); +} +mod get_u64 { + use super::*; + bench_group!(get_u64); +} +mod get_f32 { + use super::*; + bench_group!(get_f32); +} +mod get_f64 { + use super::*; + bench_group!(get_f64); +} +mod get_uint24 { + use super::*; + bench_group!(get_uint, 3); +} diff --git a/benches/bytes.rs b/benches/bytes.rs new file mode 100644 index 0000000..9c36e60 --- /dev/null +++ b/benches/bytes.rs @@ -0,0 +1,118 @@ +#![feature(test)] +#![deny(warnings, rust_2018_idioms)] + +extern crate test; + +use test::Bencher; +use bytes::Bytes; + +#[bench] +fn deref_unique(b: &mut Bencher) { + let buf = Bytes::from(vec![0; 1024]); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_shared(b: &mut Bencher) { + let buf = Bytes::from(vec![0; 1024]); + let _b2 = buf.clone(); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_static(b: &mut Bencher) { + let buf = Bytes::from_static(b"hello world"); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn clone_static(b: &mut Bencher) { + let bytes = Bytes::from_static("hello world 1234567890 and have a good byte 0987654321".as_bytes()); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&bytes.clone()); + } + }) +} + +#[bench] +fn clone_shared(b: &mut Bencher) { + let bytes = Bytes::from(b"hello world 1234567890 and have a good byte 0987654321".to_vec()); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&bytes.clone()); + } + }) +} + +#[bench] +fn clone_arc_vec(b: &mut Bencher) { + use std::sync::Arc; + let bytes = Arc::new(b"hello world 1234567890 and have a good byte 0987654321".to_vec()); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&bytes.clone()); + } + }) +} + +#[bench] +fn from_long_slice(b: &mut Bencher) { + let data = [0u8; 128]; + b.bytes = data.len() as u64; + b.iter(|| { + let buf = Bytes::copy_from_slice(&data[..]); + test::black_box(buf); + }) +} + +#[bench] +fn slice_empty(b: &mut Bencher) { + b.iter(|| { + let b = Bytes::from(vec![17; 1024]).clone(); + for i in 0..1000 { + test::black_box(b.slice(i % 100..i % 100)); + } + }) +} + +#[bench] +fn slice_short_from_arc(b: &mut Bencher) { + b.iter(|| { + // `clone` is to convert to ARC + let b = Bytes::from(vec![17; 1024]).clone(); + for i in 0..1000 { + test::black_box(b.slice(1..2 + i % 10)); + } + }) +} + +#[bench] +fn split_off_and_drop(b: &mut Bencher) { + b.iter(|| { + for _ in 0..1024 { + let v = vec![10; 200]; + let mut b = Bytes::from(v); + test::black_box(b.split_off(100)); + test::black_box(b); + } + }) +} diff --git a/benches/bytes_mut.rs b/benches/bytes_mut.rs new file mode 100644 index 0000000..ded1d14 --- /dev/null +++ b/benches/bytes_mut.rs @@ -0,0 +1,249 @@ +#![feature(test)] +#![deny(warnings, rust_2018_idioms)] + +extern crate test; + +use test::Bencher; +use bytes::{BufMut, BytesMut}; + +#[bench] +fn alloc_small(b: &mut Bencher) { + b.iter(|| { + for _ in 0..1024 { + test::black_box(BytesMut::with_capacity(12)); + } + }) +} + +#[bench] +fn alloc_mid(b: &mut Bencher) { + b.iter(|| { + test::black_box(BytesMut::with_capacity(128)); + }) +} + +#[bench] +fn alloc_big(b: &mut Bencher) { + b.iter(|| { + test::black_box(BytesMut::with_capacity(4096)); + }) +} + + +#[bench] +fn deref_unique(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(4096); + buf.put(&[0u8; 1024][..]); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_unique_unroll(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(4096); + buf.put(&[0u8; 1024][..]); + + b.iter(|| { + for _ in 0..128 { + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_shared(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(4096); + buf.put(&[0u8; 1024][..]); + let _b2 = buf.split_off(1024); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&buf[..]); + } + }) +} + +#[bench] +fn deref_two(b: &mut Bencher) { + let mut buf1 = BytesMut::with_capacity(8); + buf1.put(&[0u8; 8][..]); + + let mut buf2 = BytesMut::with_capacity(4096); + buf2.put(&[0u8; 1024][..]); + + b.iter(|| { + for _ in 0..512 { + test::black_box(&buf1[..]); + test::black_box(&buf2[..]); + } + }) +} + +#[bench] +fn clone_frozen(b: &mut Bencher) { + let bytes = BytesMut::from(&b"hello world 1234567890 and have a good byte 0987654321"[..]).split().freeze(); + + b.iter(|| { + for _ in 0..1024 { + test::black_box(&bytes.clone()); + } + }) +} + +#[bench] +fn alloc_write_split_to_mid(b: &mut Bencher) { + b.iter(|| { + let mut buf = BytesMut::with_capacity(128); + buf.put_slice(&[0u8; 64]); + test::black_box(buf.split_to(64)); + }) +} + +#[bench] +fn drain_write_drain(b: &mut Bencher) { + let data = [0u8; 128]; + + b.iter(|| { + let mut buf = BytesMut::with_capacity(1024); + let mut parts = Vec::with_capacity(8); + + for _ in 0..8 { + buf.put(&data[..]); + parts.push(buf.split_to(128)); + } + + test::black_box(parts); + }) +} + +#[bench] +fn fmt_write(b: &mut Bencher) { + use std::fmt::Write; + let mut buf = BytesMut::with_capacity(128); + let s = "foo bar baz quux lorem ipsum dolor et"; + + b.bytes = s.len() as u64; + b.iter(|| { + let _ = write!(buf, "{}", s); + test::black_box(&buf); + unsafe { buf.set_len(0); } + }) +} + +#[bench] +fn bytes_mut_extend(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.extend(&data); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} + +// BufMut for BytesMut vs Vec + +#[bench] +fn put_slice_bytes_mut(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.put_slice(&data); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} + +#[bench] +fn put_u8_bytes_mut(b: &mut Bencher) { + let mut buf = BytesMut::with_capacity(256); + let cnt = 128; + + b.bytes = cnt as u64; + b.iter(|| { + for _ in 0..cnt { + buf.put_u8(b'x'); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} + +#[bench] +fn put_slice_vec(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.put_slice(&data); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} + +#[bench] +fn put_u8_vec(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let cnt = 128; + + b.bytes = cnt as u64; + b.iter(|| { + for _ in 0..cnt { + buf.put_u8(b'x'); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} + +#[bench] +fn put_slice_vec_extend(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let data = [33u8; 32]; + + b.bytes = data.len() as u64 * 4; + b.iter(|| { + for _ in 0..4 { + buf.extend_from_slice(&data); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} + +#[bench] +fn put_u8_vec_push(b: &mut Bencher) { + let mut buf = Vec::::with_capacity(256); + let cnt = 128; + + b.bytes = cnt as u64; + b.iter(|| { + for _ in 0..cnt { + buf.push(b'x'); + } + test::black_box(&buf); + unsafe { buf.set_len(0); } + }); +} -- cgit v1.2.3