From 3f5890be70e093760d85066f9102d9e2b48cf84b Mon Sep 17 00:00:00 2001
From: Stepan Koltsov <stepan.koltsov@gmail.com>
Date: Mon, 22 May 2017 23:15:08 +0300
Subject: [PATCH] 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
```
---
 benches/bytes.rs    | 22 +++++++++++++++++++++-
 src/bytes.rs        |  5 +++++
 tests/test_bytes.rs |  9 +++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/benches/bytes.rs b/benches/bytes.rs
index 4232ced..ff07395 100644
--- a/benches/bytes.rs
+++ b/benches/bytes.rs
@@ -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);
+        }
+    })
+}
diff --git a/src/bytes.rs b/src/bytes.rs
index 6246509..4b0ef42 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -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 {
diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs
index af481a2..c8d23d3 100644
--- a/tests/test_bytes.rs
+++ b/tests/test_bytes.rs
@@ -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"[..]);
 
-- 
GitLab