Skip to content

Commit 5f1c803

Browse files
committed
Add basic runtime benchmarks for fast-vec optimisations
Refs jam1garner#319.
1 parent 67bea40 commit 5f1c803

File tree

4 files changed

+134
-23
lines changed

4 files changed

+134
-23
lines changed

binrw/tests/benches.rs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![cfg_attr(all(nightly, not(coverage)), feature(test))]
2+
3+
#[cfg(all(nightly, not(coverage)))]
4+
#[path = "benches/fast_vec.rs"]
5+
mod fast_vec;

binrw/tests/benches/fast_vec.rs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#[path = "../test_utils/mod.rs"]
2+
mod test_utils;
3+
4+
extern crate test;
5+
6+
use binrw::BinRead;
7+
8+
#[cfg(target_endian = "big")]
9+
const ENDIAN: binrw::Endian = binrw::Endian::Little;
10+
#[cfg(target_endian = "little")]
11+
const ENDIAN: binrw::Endian = binrw::Endian::Big;
12+
13+
macro_rules! bench_fast {
14+
($($name:ident, $Ty:ty, $reads:literal);+$(;)?) => {
15+
$(#[bench]
16+
fn $name(b: &mut test::Bencher) {
17+
run_benchmark::<$Ty>(b, binrw::Endian::NATIVE, $reads);
18+
})+
19+
}
20+
}
21+
22+
macro_rules! bench_fast_swap {
23+
($($name:ident, $Ty:ty, $reads:literal);+$(;)?) => {
24+
$(#[bench]
25+
fn $name(b: &mut test::Bencher) {
26+
run_benchmark::<$Ty>(b, ENDIAN, $reads);
27+
})+
28+
}
29+
}
30+
31+
#[inline(always)]
32+
fn run_benchmark<T>(b: &mut test::Bencher, endian: binrw::Endian, expected_reads: usize)
33+
where
34+
T: for<'a> BinRead<Args<'a> = ()> + 'static,
35+
{
36+
let mut filler = test_utils::Fill::new(1);
37+
let count: usize = 65536 / core::mem::size_of::<T>();
38+
39+
b.iter(|| {
40+
let mut counter = test_utils::Counter::new(&mut filler);
41+
42+
test::black_box(
43+
Vec::<T>::read_options(
44+
&mut counter,
45+
endian,
46+
binrw::VecArgs::builder().count(count).finalize(),
47+
)
48+
.unwrap(),
49+
);
50+
51+
assert_eq!(counter.reads, expected_reads);
52+
});
53+
}
54+
55+
bench_fast!(
56+
vec_i8, i8, 12;
57+
vec_u8, u8, 4;
58+
vec_i16, i16, 12;
59+
vec_u16, u16, 12;
60+
vec_i32, i32, 12;
61+
vec_u32, u32, 12;
62+
vec_i64, i64, 12;
63+
vec_u64, u64, 12;
64+
vec_i128, i128, 11;
65+
vec_u128, u128, 11;
66+
);
67+
68+
bench_fast_swap!(
69+
vec_i16_swap, i16, 12;
70+
vec_u16_swap, u16, 12;
71+
vec_i32_swap, i32, 12;
72+
vec_u32_swap, u32, 12;
73+
vec_i64_swap, i64, 12;
74+
vec_u64_swap, u64, 12;
75+
vec_i128_swap, i128, 11;
76+
vec_u128_swap, u128, 11;
77+
);

binrw/tests/io/bufreader.rs

+4-23
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,12 @@
22
use binrw::io::{BufReader, Cursor, Read, Seek, SeekFrom};
33
use std::io::BufRead;
44

5+
#[path = "../test_utils/mod.rs"]
6+
mod test_utils;
7+
58
#[test]
69
fn bufreader() {
7-
struct Counter<T> {
8-
inner: T,
9-
reads: usize,
10-
}
11-
12-
impl<T> Counter<T> {
13-
fn new(inner: T) -> Self {
14-
Counter { inner, reads: 0 }
15-
}
16-
}
17-
18-
impl<T: Read> Read for Counter<T> {
19-
fn read(&mut self, buf: &mut [u8]) -> binrw::io::Result<usize> {
20-
self.reads += 1;
21-
self.inner.read(buf)
22-
}
23-
}
24-
25-
impl<T: Seek> Seek for Counter<T> {
26-
fn seek(&mut self, pos: SeekFrom) -> binrw::io::Result<u64> {
27-
self.inner.seek(pos)
28-
}
29-
}
10+
use test_utils::Counter;
3011

3112
let mut stream = Cursor::new(b"helloworld".to_vec());
3213
// Give wrapped stream a non-zero position first to ensure it is adopted

binrw/tests/test_utils/mod.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use binrw::io::{Read, Seek, SeekFrom};
2+
3+
pub(crate) struct Fill {
4+
value: u8,
5+
}
6+
7+
impl Fill {
8+
pub(crate) fn new(value: u8) -> Self {
9+
Self { value }
10+
}
11+
}
12+
13+
impl Read for Fill {
14+
fn read(&mut self, buf: &mut [u8]) -> binrw::io::Result<usize> {
15+
buf.fill(self.value);
16+
Ok(buf.len())
17+
}
18+
}
19+
20+
impl Seek for Fill {
21+
fn seek(&mut self, _: SeekFrom) -> binrw::io::Result<u64> {
22+
Ok(0)
23+
}
24+
}
25+
26+
pub(crate) struct Counter<T> {
27+
pub(crate) inner: T,
28+
pub(crate) reads: usize,
29+
}
30+
31+
impl<T> Counter<T> {
32+
pub(crate) fn new(inner: T) -> Self {
33+
Counter { inner, reads: 0 }
34+
}
35+
}
36+
37+
impl<T: Read> Read for Counter<T> {
38+
fn read(&mut self, buf: &mut [u8]) -> binrw::io::Result<usize> {
39+
self.reads += 1;
40+
self.inner.read(buf)
41+
}
42+
}
43+
44+
impl<T: Seek> Seek for Counter<T> {
45+
fn seek(&mut self, pos: SeekFrom) -> binrw::io::Result<u64> {
46+
self.inner.seek(pos)
47+
}
48+
}

0 commit comments

Comments
 (0)