use bencher::{Bencher, benchmark_group, benchmark_main, black_box};
use buf_ref_reader::*;
use std::io::{Read, BufRead, BufReader, Result};
use memchr::memchr;
use std::{thread, time};
static WORDS: &'static [u8] = include_bytes!("/usr/share/dict/words");
struct ThrottledReader<R: Read>(R);
impl<R: Read> Read for ThrottledReader<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
thread::sleep(time::Duration::from_nanos(1));
self.0.read(buf)
}
}
fn consume(data: &[u8]) {
black_box(data);
}
macro_rules! bufref {
($fname:ident, $buf:ident, $wrapped:expr, $cap:expr) => {
fn $fname(b: &mut Bencher) {
b.iter(|| {
let mut r = BufRefReaderBuilder::new($wrapped)
.capacity($cap)
.build::<$buf>()
.unwrap();
while let Some(line) = r.read_until(b'\n').unwrap() {
consume(line);
}
})
}
}
}
bufref!(bufref_read_until_vec_4, VecBuffer, WORDS, 4096);
bufref!(bufref_read_until_vec_64, VecBuffer, WORDS, 64*1024);
bufref!(bufref_read_until_mmap_4, MmapBuffer, WORDS, 4096);
bufref!(bufref_read_until_mmap_64, MmapBuffer, WORDS, 64*1024);
bufref!(throttled_bufref_read_until_vec_4, VecBuffer, ThrottledReader(WORDS), 4096);
bufref!(throttled_bufref_read_until_vec_64, VecBuffer, ThrottledReader(WORDS), 64*1024);
bufref!(throttled_bufref_read_until_mmap_4, MmapBuffer, ThrottledReader(WORDS), 4096);
bufref!(throttled_bufref_read_until_mmap_64, MmapBuffer, ThrottledReader(WORDS), 64*1024);
macro_rules! std_read_until {
($fname:ident, $wrapped:expr, $cap:expr) => {
fn $fname(b: &mut Bencher) {
b.iter(|| {
let mut r = BufReader::with_capacity($cap, $wrapped);
let mut buf = vec![];
while r.read_until(b'\n', &mut buf).unwrap() != 0 {
consume(buf.as_slice());
buf.clear();
}
})
}
}
}
std_read_until!(std_read_until_4, WORDS, 4096);
std_read_until!(std_read_until_64, WORDS, 64*1024);
std_read_until!(throttled_std_read_until_4, ThrottledReader(WORDS), 4096);
std_read_until!(throttled_std_read_until_64, ThrottledReader(WORDS), 64*1024);
macro_rules! std_fillbuf {
($fname:ident, $wrapped:expr, $cap:expr) => {
fn $fname(b: &mut Bencher) {
b.iter(|| {
let mut r = BufReader::with_capacity($cap, $wrapped);
let mut head: Option<Vec<u8>> = None;
loop {
let buf = r.fill_buf().unwrap();
if buf.len() == 0 {
if let Some(head) = &mut head {
consume(head.as_slice());
}
break;
}
match memchr(b'\n', buf) {
Some(len) => {
let tail = &buf[..len];
let s = if let Some(head) = &mut head {
head.extend_from_slice(tail);
head.as_slice()
} else {
tail
};
consume(s);
head = None;
r.consume(len+1);
},
None => {
if let Some(head) = &mut head {
head.extend_from_slice(buf);
} else {
head = Some(buf.to_vec());
}
let len = buf.len();
r.consume(len);
},
}
}
})
}
}
}
std_fillbuf!(std_fillbuf_4, WORDS, 4096);
std_fillbuf!(std_fillbuf_64, WORDS, 64*1024);
std_fillbuf!(throttled_std_fillbuf_4, ThrottledReader(WORDS), 4096);
std_fillbuf!(throttled_std_fillbuf_64, ThrottledReader(WORDS), 64*1024);
macro_rules! bufref_read_until_long {
($fname:ident, $buf:ident, $wrapped:expr, $cap:expr) => {
fn $fname(b: &mut Bencher) {
b.iter(|| {
let mut r = BufRefReaderBuilder::new($wrapped)
.capacity($cap)
.build::<$buf>()
.unwrap();
while let Some(x) = r.read_until(b'q').unwrap() {
consume(x);
}
})
}
}
}
bufref_read_until_long!(bufref_read_until_long_vec_4, VecBuffer, WORDS, 4096);
bufref_read_until_long!(bufref_read_until_long_vec_64, VecBuffer, WORDS, 64*1024);
bufref_read_until_long!(bufref_read_until_long_mmap_4, MmapBuffer, WORDS, 4096);
bufref_read_until_long!(bufref_read_until_long_mmap_64, MmapBuffer, WORDS, 64*1024);
bufref_read_until_long!(throttled_bufref_read_until_long_vec_4, VecBuffer, ThrottledReader(WORDS), 4096);
bufref_read_until_long!(throttled_bufref_read_until_long_vec_64, VecBuffer, ThrottledReader(WORDS), 64*1024);
bufref_read_until_long!(throttled_bufref_read_until_long_mmap_4, MmapBuffer, ThrottledReader(WORDS), 4096);
bufref_read_until_long!(throttled_bufref_read_until_long_mmap_64, MmapBuffer, ThrottledReader(WORDS), 64*1024);
macro_rules! std_read_until_long {
($fname:ident, $wrapped:expr, $cap:expr) => {
fn $fname(b: &mut Bencher) {
b.iter(|| {
let mut r = BufReader::with_capacity($cap, $wrapped);
let mut buf = vec![];
while r.read_until(b'q', &mut buf).unwrap() != 0 {
consume(buf.as_slice());
buf.clear();
}
})
}
}
}
std_read_until_long!(std_read_until_long_4, WORDS, 4096);
std_read_until_long!(std_read_until_long_64, WORDS, 64*1024);
std_read_until_long!(throttled_std_read_until_long_4, ThrottledReader(WORDS), 4096);
std_read_until_long!(throttled_std_read_until_long_64, ThrottledReader(WORDS), 64*1024);
benchmark_group!(benches,
bufref_read_until_vec_4,
bufref_read_until_vec_64,
bufref_read_until_mmap_4,
bufref_read_until_mmap_64,
throttled_bufref_read_until_vec_4,
throttled_bufref_read_until_vec_64,
throttled_bufref_read_until_mmap_4,
throttled_bufref_read_until_mmap_64,
std_read_until_4,
std_read_until_64,
throttled_std_read_until_4,
throttled_std_read_until_64,
std_fillbuf_4,
std_fillbuf_64,
throttled_std_fillbuf_4,
throttled_std_fillbuf_64,
bufref_read_until_long_vec_4,
bufref_read_until_long_vec_64,
bufref_read_until_long_mmap_4,
bufref_read_until_long_mmap_64,
throttled_bufref_read_until_long_vec_4,
throttled_bufref_read_until_long_vec_64,
throttled_bufref_read_until_long_mmap_4,
throttled_bufref_read_until_long_mmap_64,
std_read_until_long_4,
std_read_until_long_64,
throttled_std_read_until_long_4,
throttled_std_read_until_long_64,
);
benchmark_main!(benches);