From 17637665e94a90faeeb306340b68e4ceaad8b844 Mon Sep 17 00:00:00 2001
From: Carl Lerche <me@carllerche.com>
Date: Mon, 9 Feb 2015 22:20:55 -0800
Subject: [PATCH] Add a quick benchmark

---
 Cargo.toml      |  2 +-
 bench/bench.rs  | 34 ++++++++++++++++++++++++++++++++++
 src/byte_buf.rs | 45 +++++++++++++++++++++++++++++----------------
 src/byte_str.rs |  2 +-
 src/lib.rs      | 25 ++++++++++++++++---------
 5 files changed, 81 insertions(+), 27 deletions(-)
 create mode 100644 bench/bench.rs

diff --git a/Cargo.toml b/Cargo.toml
index f88a5eb..657cbc6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ license     = "MIT"
 [dev-dependencies]
 
 rand = "0.1.2"
-# iobuf = "*"
+iobuf = "*"
 
 
 [[bench]]
diff --git a/bench/bench.rs b/bench/bench.rs
new file mode 100644
index 0000000..fc561aa
--- /dev/null
+++ b/bench/bench.rs
@@ -0,0 +1,34 @@
+#![feature(test, core)]
+
+use bytes::ByteBuf;
+use bytes::traits::*;
+use iobuf::{RWIobuf};
+use test::Bencher;
+
+extern crate bytes;
+extern crate iobuf;
+extern crate test;
+
+const SIZE:usize = 4_096;
+
+#[bench]
+pub fn bench_byte_buf_fill_4kb(b: &mut Bencher) {
+    b.iter(|| {
+        let mut buf = ByteBuf::mut_with_capacity(SIZE);
+
+        for _ in 0..SIZE {
+            buf.write_slice(&[0]);
+        }
+    });
+}
+
+#[bench]
+pub fn bench_rw_iobuf_fill_4kb(b: &mut Bencher) {
+    b.iter(|| {
+        let mut buf = RWIobuf::new(SIZE);
+
+        for _ in 0..SIZE {
+            let _ = buf.fill(&[0]);
+        }
+    });
+}
diff --git a/src/byte_buf.rs b/src/byte_buf.rs
index 14f5006..96a40b9 100644
--- a/src/byte_buf.rs
+++ b/src/byte_buf.rs
@@ -1,5 +1,5 @@
-use {alloc, Bytes, SeqByteStr, BufResult, BufError, MAX_CAPACITY};
-use traits::{Buf, MutBuf, ByteStr};
+use {alloc, Bytes, SeqByteStr, MAX_CAPACITY};
+use traits::{Buf, MutBuf, MutBufExt, ByteStr};
 use std::{cmp, ptr};
 use std::num::UnsignedInt;
 
@@ -9,6 +9,7 @@ use std::num::UnsignedInt;
  *
  */
 
+/// A `Buf` backed by a contiguous region of memory.
 pub struct ByteBuf {
     mem: alloc::MemRef,
     cap: u32,
@@ -17,6 +18,7 @@ pub struct ByteBuf {
 }
 
 impl ByteBuf {
+    /// Create a new `ByteBuf` by copying the contents of the given slice.
     pub fn from_slice(bytes: &[u8]) -> ByteBuf {
         let mut buf = ByteBuf::mut_with_capacity(bytes.len());
         buf.write(bytes).ok().expect("unexpected failure");
@@ -105,45 +107,46 @@ impl ByteBuf {
         }
     }
 
+    #[inline]
     pub fn to_bytes(self) -> Bytes {
         Bytes::of(self.to_seq_byte_str())
     }
 
+    #[inline]
     fn pos(&self) -> usize {
         self.pos as usize
     }
 
+    #[inline]
     fn lim(&self) -> usize {
         self.lim as usize
     }
 
+    #[inline]
     fn remaining_u32(&self) -> u32 {
         self.lim - self.pos
     }
-
-    fn ensure_remaining(&self, cnt: usize) -> BufResult<()> {
-        if cnt > self.remaining() {
-            return Err(BufError::Overflow);
-        }
-
-        Ok(())
-    }
 }
 
 impl Buf for ByteBuf {
+
+    #[inline]
     fn remaining(&self) -> usize {
         self.remaining_u32() as usize
     }
 
+    #[inline]
     fn bytes<'a>(&'a self) -> &'a [u8] {
         &self.mem.bytes()[self.pos()..self.lim()]
     }
 
+    #[inline]
     fn advance(&mut self, mut cnt: usize) {
         cnt = cmp::min(cnt, self.remaining());
         self.pos += cnt as u32;
     }
 
+    #[inline]
     fn read_slice(&mut self, dst: &mut [u8]) -> usize {
         ByteBuf::read_slice(self, dst)
     }
@@ -225,18 +228,28 @@ impl MutByteBuf {
         self.buf.lim = self.buf.cap;
     }
 
-    pub fn write_slice(&mut self, src: &[u8]) -> BufResult<()> {
-        try!(self.buf.ensure_remaining(src.len()));
+    #[inline]
+    pub fn write_slice(&mut self, src: &[u8]) -> usize {
         let cnt = src.len() as u32;
+        let rem = self.buf.remaining_u32();
 
+        if rem < cnt {
+            self.write_ptr(src.as_ptr(), rem)
+        } else {
+            self.write_ptr(src.as_ptr(), cnt)
+        }
+    }
+
+    #[inline]
+    fn write_ptr(&mut self, src: *const u8, len: u32) -> usize {
         unsafe {
             ptr::copy_nonoverlapping_memory(
                 self.buf.mem.ptr().offset(self.buf.pos as isize),
-                src.as_ptr(), src.len());
-        }
+                src, len as usize);
 
-        self.buf.pos += cnt;
-        return Ok(());
+            self.buf.pos += len;
+            len as usize
+        }
     }
 }
 
diff --git a/src/byte_str.rs b/src/byte_str.rs
index 2cccebf..ee420cf 100644
--- a/src/byte_str.rs
+++ b/src/byte_str.rs
@@ -1,5 +1,5 @@
 use {alloc, Bytes, ByteBuf, ROByteBuf};
-use traits::{Buf, MutBuf, ByteStr};
+use traits::{Buf, MutBuf, MutBufExt, ByteStr};
 use std::{cmp, ops};
 
 /*
diff --git a/src/lib.rs b/src/lib.rs
index d8843dc..5a4eb88 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,12 +24,12 @@ mod rope;
 mod slice;
 
 pub mod traits {
-    pub use {Buf, BufExt, MutBuf, ByteStr};
+    pub use {Buf, BufExt, MutBuf, MutBufExt, ByteStr};
 }
 
 const MAX_CAPACITY: usize = u32::MAX as usize;
 
-/// A trait for objects that provide random and sequential access to bytes.
+/// A trait for values that provide random and sequential access to bytes.
 pub trait Buf {
 
     /// Returns the number of bytes that can be accessed from the Buf
@@ -113,12 +113,6 @@ pub trait MutBuf : Sized {
     /// length between 0 and `Buf::remaining()`.
     fn mut_bytes<'a>(&'a mut self) -> &'a mut [u8];
 
-    /// Read bytes from this Buf into the given sink and advance the cursor by
-    /// the number of bytes read.
-    fn write<S: Source>(&mut self, src: S) -> Result<usize, S::Error> {
-        src.fill(self)
-    }
-
     /// Read bytes from this Buf into the given slice and advance the cursor by
     /// the number of bytes read.
     ///
@@ -164,6 +158,13 @@ pub trait MutBuf : Sized {
     }
 }
 
+pub trait MutBufExt {
+
+    /// Write bytes from the given source into the current `MutBuf` and advance
+    /// the cursor by the number of bytes written.
+    fn write<S: Source>(&mut self, src: S) -> Result<usize, S::Error>;
+}
+
 /*
  *
  * ===== ByteStr =====
@@ -239,13 +240,19 @@ impl<B: Buf> BufExt for B {
     }
 }
 
+impl<B: MutBuf> MutBufExt for B {
+    fn write<S: Source>(&mut self, src: S) -> Result<usize, S::Error> {
+        src.fill(self)
+    }
+}
+
 /*
  *
  * ===== Sink / Source =====
  *
  */
 
-/// An object that reads bytes from a Buf into itself
+/// An value that reads bytes from a Buf into itself
 pub trait Sink {
     type Error;
 
-- 
GitLab