mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-10 23:12:39 +00:00
187 lines
5.1 KiB
Rust
187 lines
5.1 KiB
Rust
#![feature(test)]
|
|
#![warn(rust_2018_idioms)]
|
|
|
|
extern crate test;
|
|
|
|
use bytes::Buf;
|
|
use test::Bencher;
|
|
|
|
/// Dummy Buf implementation
|
|
struct TestBuf {
|
|
buf: &'static [u8],
|
|
readlens: &'static [usize],
|
|
init_pos: usize,
|
|
pos: usize,
|
|
readlen_pos: usize,
|
|
readlen: usize,
|
|
}
|
|
impl TestBuf {
|
|
fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBuf {
|
|
let mut buf = TestBuf {
|
|
buf,
|
|
readlens,
|
|
init_pos,
|
|
pos: 0,
|
|
readlen_pos: 0,
|
|
readlen: 0,
|
|
};
|
|
buf.reset();
|
|
buf
|
|
}
|
|
fn reset(&mut self) {
|
|
self.pos = self.init_pos;
|
|
self.readlen_pos = 0;
|
|
self.next_readlen();
|
|
}
|
|
/// Compute the length of the next read :
|
|
/// - use the next value specified in readlens (capped by remaining) if any
|
|
/// - else the remaining
|
|
fn next_readlen(&mut self) {
|
|
self.readlen = self.buf.len() - self.pos;
|
|
if let Some(readlen) = self.readlens.get(self.readlen_pos) {
|
|
self.readlen = std::cmp::min(self.readlen, *readlen);
|
|
self.readlen_pos += 1;
|
|
}
|
|
}
|
|
}
|
|
impl Buf for TestBuf {
|
|
fn remaining(&self) -> usize {
|
|
return self.buf.len() - self.pos;
|
|
}
|
|
fn advance(&mut self, cnt: usize) {
|
|
self.pos += cnt;
|
|
assert!(self.pos <= self.buf.len());
|
|
self.next_readlen();
|
|
}
|
|
fn chunk(&self) -> &[u8] {
|
|
if self.readlen == 0 {
|
|
Default::default()
|
|
} else {
|
|
&self.buf[self.pos..self.pos + self.readlen]
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Dummy Buf implementation
|
|
/// version with methods forced to not be inlined (to simulate costly calls)
|
|
struct TestBufC {
|
|
inner: TestBuf,
|
|
}
|
|
impl TestBufC {
|
|
fn new(buf: &'static [u8], readlens: &'static [usize], init_pos: usize) -> TestBufC {
|
|
TestBufC {
|
|
inner: TestBuf::new(buf, readlens, init_pos),
|
|
}
|
|
}
|
|
fn reset(&mut self) {
|
|
self.inner.reset()
|
|
}
|
|
}
|
|
impl Buf for TestBufC {
|
|
#[inline(never)]
|
|
fn remaining(&self) -> usize {
|
|
self.inner.remaining()
|
|
}
|
|
#[inline(never)]
|
|
fn advance(&mut self, cnt: usize) {
|
|
self.inner.advance(cnt)
|
|
}
|
|
#[inline(never)]
|
|
fn chunk(&self) -> &[u8] {
|
|
self.inner.chunk()
|
|
}
|
|
}
|
|
|
|
macro_rules! bench {
|
|
($fname:ident, testbuf $testbuf:ident $readlens:expr, $method:ident $(,$arg:expr)*) => (
|
|
#[bench]
|
|
fn $fname(b: &mut Bencher) {
|
|
let mut bufs = [
|
|
$testbuf::new(&[1u8; 8+0], $readlens, 0),
|
|
$testbuf::new(&[1u8; 8+1], $readlens, 1),
|
|
$testbuf::new(&[1u8; 8+2], $readlens, 2),
|
|
$testbuf::new(&[1u8; 8+3], $readlens, 3),
|
|
$testbuf::new(&[1u8; 8+4], $readlens, 4),
|
|
$testbuf::new(&[1u8; 8+5], $readlens, 5),
|
|
$testbuf::new(&[1u8; 8+6], $readlens, 6),
|
|
$testbuf::new(&[1u8; 8+7], $readlens, 7),
|
|
];
|
|
b.iter(|| {
|
|
for i in 0..8 {
|
|
bufs[i].reset();
|
|
let buf: &mut dyn Buf = &mut bufs[i]; // type erasure
|
|
test::black_box(buf.$method($($arg,)*));
|
|
}
|
|
})
|
|
}
|
|
);
|
|
($fname:ident, slice, $method:ident $(,$arg:expr)*) => (
|
|
#[bench]
|
|
fn $fname(b: &mut Bencher) {
|
|
// buf must be long enough for one read of 8 bytes starting at pos 7
|
|
let arr = [1u8; 8+7];
|
|
b.iter(|| {
|
|
for i in 0..8 {
|
|
let mut buf = &arr[i..];
|
|
let buf = &mut buf as &mut dyn Buf; // type erasure
|
|
test::black_box(buf.$method($($arg,)*));
|
|
}
|
|
})
|
|
}
|
|
);
|
|
($fname:ident, option) => (
|
|
#[bench]
|
|
fn $fname(b: &mut Bencher) {
|
|
let data = [1u8; 1];
|
|
b.iter(|| {
|
|
for _ in 0..8 {
|
|
let mut buf = Some(data);
|
|
let buf = &mut buf as &mut dyn Buf; // type erasure
|
|
test::black_box(buf.get_u8());
|
|
}
|
|
})
|
|
}
|
|
);
|
|
}
|
|
|
|
macro_rules! bench_group {
|
|
($method:ident $(,$arg:expr)*) => (
|
|
bench!(slice, slice, $method $(,$arg)*);
|
|
bench!(tbuf_1, testbuf TestBuf &[], $method $(,$arg)*);
|
|
bench!(tbuf_1_costly, testbuf TestBufC &[], $method $(,$arg)*);
|
|
bench!(tbuf_2, testbuf TestBuf &[1], $method $(,$arg)*);
|
|
bench!(tbuf_2_costly, testbuf TestBufC &[1], $method $(,$arg)*);
|
|
// bench!(tbuf_onebyone, testbuf TestBuf &[1,1,1,1,1,1,1,1], $method $(,$arg)*);
|
|
// bench!(tbuf_onebyone_costly, testbuf TestBufC &[1,1,1,1,1,1,1,1], $method $(,$arg)*);
|
|
);
|
|
}
|
|
|
|
mod get_u8 {
|
|
use super::*;
|
|
bench_group!(get_u8);
|
|
}
|
|
mod get_u16 {
|
|
use super::*;
|
|
bench_group!(get_u16);
|
|
}
|
|
mod get_u32 {
|
|
use super::*;
|
|
bench_group!(get_u32);
|
|
}
|
|
mod get_u64 {
|
|
use super::*;
|
|
bench_group!(get_u64);
|
|
}
|
|
mod get_f32 {
|
|
use super::*;
|
|
bench_group!(get_f32);
|
|
}
|
|
mod get_f64 {
|
|
use super::*;
|
|
bench_group!(get_f64);
|
|
}
|
|
mod get_uint24 {
|
|
use super::*;
|
|
bench_group!(get_uint, 3);
|
|
}
|