Skip to content

Instantly share code, notes, and snippets.

Created March 13, 2015 07:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/74506f7daa102b6fa32b to your computer and use it in GitHub Desktop.
Save anonymous/74506f7daa102b6fa32b to your computer and use it in GitHub Desktop.
extern crate test;
use std::io::prelude::*;
use std::io;
use std::mem;
use std::cmp;
use std::slice;
struct MyBufWriter1<'a> {
buf: &'a mut [u8],
}
impl<'a> MyBufWriter1<'a> {
pub fn new(buf: &'a mut [u8]) -> MyBufWriter1<'a> {
MyBufWriter1 {
buf: buf,
}
}
}
impl<'a> io::Write for MyBufWriter1<'a> {
#[inline]
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
let amt = cmp::min(data.len(), self.buf.len());
let (a, b) = mem::replace(&mut self.buf, &mut []).split_at_mut(amt);
slice::bytes::copy_memory(a, &data[..amt]);
self.buf = b;
Ok(amt)
}
#[inline]
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
if try!(self.write(data)) == data.len() {
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::WriteZero, "failed to write whole buffer", None))
}
}
#[inline]
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
struct MyBufWriter2<'a> {
dst: &'a mut [u8],
}
impl<'a> MyBufWriter2<'a> {
pub fn new(buf: &'a mut [u8]) -> MyBufWriter2<'a> {
MyBufWriter2 {
dst: buf,
}
}
}
impl<'a> io::Write for MyBufWriter2<'a> {
fn write(&mut self, _data: &[u8]) -> io::Result<usize> {
panic!()
}
fn write_all(&mut self, src: &[u8]) -> io::Result<()> {
use std::raw;
use std::ptr;
let dst_len = self.dst.len();
if dst_len == 0 {
return Err(io::Error::new(io::ErrorKind::WriteZero, "failed to write whole buffer", None));
}
let src_len = src.len();
if dst_len >= src_len {
unsafe {
ptr::copy_nonoverlapping(
self.dst.as_mut_ptr(),
src.as_ptr(),
src_len);
self.dst = mem::transmute(raw::Slice {
data: self.dst.as_ptr().offset(src_len as isize),
len: dst_len - src_len,
});
}
Ok(())
} else {
unsafe {
ptr::copy_nonoverlapping(
self.dst.as_mut_ptr(),
src.as_ptr(),
dst_len);
self.dst = mem::transmute(raw::Slice {
data: self.dst.as_ptr().offset(dst_len as isize),
len: 0,
});
}
Err(io::Error::new(io::ErrorKind::WriteZero, "failed to write whole buffer", None))
}
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
static DATA: [u8; 1 * 1024] = [1; 1 * 1024];
#[inline(never)]
fn bh<W: Write>(w: &mut W) {
for _ in 0..64 {
w.write_all(&DATA).unwrap();
}
}
#[bench]
fn b1(b: &mut test::Bencher) {
let mut a = [0; 64 * 1024];
b.iter(|| {
bh(&mut MyBufWriter1::new(&mut a[..]))
});
b.bytes = a.len() as u64;
}
#[bench]
fn b2(b: &mut test::Bencher) {
let mut a = [0; 64 * 1024];
b.iter(|| {
bh(&mut MyBufWriter2::new(&mut a[..]))
});
b.bytes = a.len() as u64;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment