Optimize Bytes::slice(n, n) (#123)

Return empty `Bytes` object

Bench for `slice_empty` difference is

```
55 ns/iter (+/- 1) # before this patch
17 ns/iter (+/- 5) # with this patch
```

Bench for `slice_not_empty` is

```
25,058 ns/iter (+/- 1,099) # before this patch
25,072 ns/iter (+/- 1,593) # with this patch
```
This commit is contained in:
Stepan Koltsov 2017-05-22 23:15:08 +03:00 committed by Carl Lerche
parent 70ee87ea29
commit 3f5890be70
3 changed files with 35 additions and 1 deletions

View file

@ -4,7 +4,7 @@ extern crate bytes;
extern crate test;
use test::Bencher;
use bytes::{BytesMut, BufMut};
use bytes::{Bytes, BytesMut, BufMut};
#[bench]
fn alloc_small(b: &mut Bencher) {
@ -126,3 +126,23 @@ fn drain_write_drain(b: &mut Bencher) {
test::black_box(parts);
})
}
#[bench]
fn slice_empty(b: &mut Bencher) {
b.iter(|| {
// Use empty vec to avoid measure of allocation/deallocation
let bytes = Bytes::from(Vec::new());
(bytes.slice(0, 0), bytes)
})
}
#[bench]
fn slice_not_empty(b: &mut Bencher) {
b.iter(|| {
let b = Bytes::from(b"aabbccddeeffgghh".to_vec());
for _ in 0..1024 {
test::black_box(b.slice(3, 5));
test::black_box(&b);
}
})
}

View file

@ -464,6 +464,11 @@ impl Bytes {
/// Requires that `begin <= end` and `end <= self.len()`, otherwise slicing
/// will panic.
pub fn slice(&self, begin: usize, end: usize) -> Bytes {
if begin == end {
assert!(begin <= self.len());
return Bytes::new();
}
let mut ret = self.clone();
unsafe {

View file

@ -79,6 +79,15 @@ fn slice() {
let b = a.slice(3, 5);
assert_eq!(b, b"lo"[..]);
let b = a.slice(0, 0);
assert_eq!(b, b""[..]);
let b = a.slice(3, 3);
assert_eq!(b, b""[..]);
let b = a.slice(a.len(), a.len());
assert_eq!(b, b""[..]);
let b = a.slice_to(5);
assert_eq!(b, b"hello"[..]);