-
-
Save sfackler/e979711b0ee2f2063462 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
#![feature(test, std_misc, thread_sleep)] | |
extern crate test; | |
use std::io::prelude::*; | |
use std::cmp; | |
use std::iter; | |
use std::time::Duration; | |
use std::thread; | |
use std::io::{self, ErrorKind}; | |
fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> io::Result<usize> | |
where F: FnOnce(&mut [u8]) -> io::Result<usize> | |
{ | |
let len = v.len(); | |
let new_area = v.capacity() - len; | |
v.extend(iter::repeat(0).take(new_area)); | |
match f(&mut v[len..]) { | |
Ok(n) => { | |
v.truncate(len + n); | |
Ok(n) | |
} | |
Err(e) => { | |
v.truncate(len); | |
Err(e) | |
} | |
} | |
} | |
fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> io::Result<usize> { | |
let mut read = 0; | |
loop { | |
if buf.capacity() == buf.len() { | |
buf.reserve(64 * 1024); | |
} | |
match with_end_to_cap(buf, |b| r.read(b)) { | |
Ok(0) => return Ok(read), | |
Ok(n) => read += n, | |
Err(ref e) if e.kind() == ErrorKind::Interrupted => {} | |
Err(e) => return Err(e), | |
} | |
} | |
} | |
fn read_to_end_new<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> io::Result<usize> { | |
let start_len = buf.len(); | |
let mut len = start_len; | |
let mut cap_bump = 16; | |
let ret; | |
loop { | |
if len == buf.len() { | |
if buf.capacity() == buf.len() { | |
if cap_bump < 64 * 1024 { | |
cap_bump *= 2; | |
} | |
buf.reserve(cap_bump); | |
} | |
let new_area = buf.capacity() - buf.len(); | |
buf.extend(iter::repeat(0).take(new_area)); | |
} | |
match r.read(&mut buf[len..]) { | |
Ok(0) => { | |
ret = Ok(len - start_len); | |
break; | |
} | |
Ok(n) => len += n, | |
Err(ref e) if e.kind() == ErrorKind::Interrupted => {} | |
Err(e) => { | |
ret = Err(e); | |
break; | |
} | |
} | |
} | |
buf.truncate(len); | |
ret | |
} | |
#[test] | |
fn test_new() { | |
let mut v = vec![1, 2, 3]; | |
assert_eq!(Ok(5), read_to_end_new(&mut io::repeat(4).take(5), &mut v)); | |
assert_eq!(vec![1, 2, 3, 4, 4, 4, 4, 4], v); | |
} | |
fn bench_std(b: &mut test::Bencher, size: u64) { | |
b.iter(|| { | |
let mut v = vec![]; | |
read_to_end(&mut io::repeat(1).take(size), &mut v) | |
}) | |
} | |
fn bench_new(b: &mut test::Bencher, size: u64) { | |
b.iter(|| { | |
let mut v = vec![]; | |
read_to_end_new(&mut io::repeat(1).take(size), &mut v) | |
}) | |
} | |
#[bench] | |
fn std_nodelay_4(b: &mut test::Bencher) { | |
bench_std(b, 4); | |
} | |
#[bench] | |
fn new_nodelay_4(b: &mut test::Bencher) { | |
bench_new(b, 4); | |
} | |
#[bench] | |
fn std_nodelay_5m(b: &mut test::Bencher) { | |
bench_std(b, 5 * 1024 * 1024); | |
} | |
#[bench] | |
fn new_nodelay_5m(b: &mut test::Bencher) { | |
bench_new(b, 5 * 1024 * 1024); | |
} | |
struct Delay<R: Read>(Duration, R); | |
impl<R: Read> Read for Delay<R> { | |
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
thread::sleep(self.0); | |
self.1.read(buf) | |
} | |
} | |
fn bench_std_delay(b: &mut test::Bencher, size: u64, delay: Duration) { | |
b.iter(|| { | |
let mut v = vec![]; | |
read_to_end(&mut Delay(delay, io::repeat(1).take(size)), &mut v) | |
}) | |
} | |
fn bench_new_delay(b: &mut test::Bencher, size: u64, delay: Duration) { | |
b.iter(|| { | |
let mut v = vec![]; | |
read_to_end_new(&mut Delay(delay, io::repeat(1).take(size)), &mut v) | |
}) | |
} | |
#[bench] | |
fn std_delay_4(b: &mut test::Bencher) { | |
bench_std_delay(b, 4, Duration::microseconds(1)); | |
} | |
#[bench] | |
fn new_delay_4(b: &mut test::Bencher) { | |
bench_new_delay(b, 4, Duration::microseconds(1)); | |
} | |
#[bench] | |
fn std_delay_5m(b: &mut test::Bencher) { | |
bench_std_delay(b, 5 * 1024 * 1024, Duration::microseconds(1)); | |
} | |
#[bench] | |
fn new_delay_5m(b: &mut test::Bencher) { | |
bench_new_delay(b, 5 * 1024 * 1024, Duration::microseconds(1)); | |
} | |
struct Cap<R: Read>(usize, R); | |
impl<R: Read> Read for Cap<R> { | |
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
let end = cmp::min(buf.len(), self.0); | |
self.1.read(&mut buf[..end]) | |
} | |
} | |
fn bench_std_delay_cap(b: &mut test::Bencher, size: u64, delay: Duration) { | |
b.iter(|| { | |
let mut v = vec![]; | |
read_to_end(&mut Cap(10240, Delay(delay, io::repeat(1).take(size))), &mut v) | |
}) | |
} | |
fn bench_new_delay_cap(b: &mut test::Bencher, size: u64, delay: Duration) { | |
b.iter(|| { | |
let mut v = vec![]; | |
read_to_end_new(&mut Cap(10240, Delay(delay, io::repeat(1).take(size))), &mut v) | |
}) | |
} | |
#[bench] | |
fn std_delay_4_cap(b: &mut test::Bencher) { | |
bench_std_delay_cap(b, 4, Duration::microseconds(1)); | |
} | |
#[bench] | |
fn new_delay_4_cap(b: &mut test::Bencher) { | |
bench_new_delay_cap(b, 4, Duration::microseconds(1)); | |
} | |
#[bench] | |
fn std_delay_5m_cap(b: &mut test::Bencher) { | |
bench_std_delay_cap(b, 5 * 1024 * 1024, Duration::microseconds(1)); | |
} | |
#[bench] | |
fn new_delay_5m_cap(b: &mut test::Bencher) { | |
bench_new_delay_cap(b, 5 * 1024 * 1024, Duration::microseconds(1)); | |
} |
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
~/foo ❯ cargo bench | |
Compiling foo v0.0.1 (file:///home/sfackler/foo) | |
Running target/release/foo-7498d7dd7faecf5c | |
running 13 tests | |
test test_new ... ignored | |
test new_delay_4 ... bench: 230768 ns/iter (+/- 14812) | |
test new_delay_4_cap ... bench: 231421 ns/iter (+/- 7211) | |
test new_delay_5m ... bench: 14495370 ns/iter (+/- 4008648) | |
test new_delay_5m_cap ... bench: 73127954 ns/iter (+/- 59908587) | |
test new_nodelay_4 ... bench: 83 ns/iter (+/- 2) | |
test new_nodelay_5m ... bench: 12527237 ns/iter (+/- 335243) | |
test std_delay_4 ... bench: 373095 ns/iter (+/- 12613) | |
test std_delay_4_cap ... bench: 374190 ns/iter (+/- 19611) | |
test std_delay_5m ... bench: 17356012 ns/iter (+/- 15906588) | |
test std_delay_5m_cap ... bench: 883555035 ns/iter (+/- 205559857) | |
test std_nodelay_4 ... bench: 144937 ns/iter (+/- 2448) | |
test std_nodelay_5m ... bench: 16095893 ns/iter (+/- 3315116) | |
test result: ok. 0 passed; 0 failed; 1 ignored; 12 measured |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment