-
-
Save alexcrichton/892847c937c49e2a3914 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
running 2 tests | |
test b1 ... bench: 2138 ns/iter (+/- 62) = 30652 MB/s | |
test b2 ... bench: 2085 ns/iter (+/- 93) = 31432 MB/s | |
test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment