mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-04 00:54:07 +02:00
253 lines
6.8 KiB
Rust
253 lines
6.8 KiB
Rust
use bitbuffer::{
|
|
BigEndian, BitRead, BitReadBuffer, BitReadStream, BitWriteStream, Endianness, LittleEndian,
|
|
};
|
|
use iai_callgrind::{library_benchmark, library_benchmark_group, main};
|
|
use std::hint::black_box;
|
|
|
|
const ONES: &[u8; 1024 * 1024 * 10] = &[1u8; 1024 * 1024 * 10];
|
|
|
|
const ONES_LE: BitReadBuffer<'static, LittleEndian> = BitReadBuffer::new(ONES, LittleEndian);
|
|
const ONES_BE: BitReadBuffer<'static, BigEndian> = BitReadBuffer::new(ONES, BigEndian);
|
|
|
|
#[library_benchmark]
|
|
#[bench::le(ONES_LE)]
|
|
#[bench::be(ONES_BE)]
|
|
fn read_perf<E: Endianness>(buffer: BitReadBuffer<E>) -> u16 {
|
|
let size = 5;
|
|
let mut pos = 0;
|
|
let len = buffer.bit_len();
|
|
let mut result: u16 = 0;
|
|
loop {
|
|
if pos + size > len {
|
|
return black_box(result);
|
|
}
|
|
let data = buffer.read_int::<u64>(pos, size).unwrap() as u16;
|
|
result = result.wrapping_add(data);
|
|
pos += size;
|
|
}
|
|
}
|
|
|
|
#[library_benchmark]
|
|
#[bench::le(ONES_LE)]
|
|
#[bench::be(ONES_BE)]
|
|
fn perf_f32<E: Endianness>(buffer: BitReadBuffer<E>) -> f32 {
|
|
let mut pos = 0;
|
|
let len = buffer.bit_len();
|
|
let mut result: f32 = 0.0;
|
|
loop {
|
|
if pos + 32 > len {
|
|
break;
|
|
}
|
|
let num = buffer.read_float::<f32>(pos).unwrap();
|
|
result += num;
|
|
pos += 32;
|
|
}
|
|
assert_eq!(result, 0.00000000000000000000000000000006170106);
|
|
black_box(result)
|
|
}
|
|
const F64_RESULT: f64 = 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010156250477904244;
|
|
|
|
#[library_benchmark]
|
|
#[bench::le(ONES_LE)]
|
|
#[bench::be(ONES_BE)]
|
|
fn perf_f64<E: Endianness>(buffer: BitReadBuffer<E>) -> f64 {
|
|
let mut pos = 0;
|
|
let len = buffer.bit_len();
|
|
let mut result: f64 = 0.0;
|
|
loop {
|
|
if pos + 64 > len {
|
|
break;
|
|
}
|
|
let num = buffer.read_float::<f64>(pos).unwrap();
|
|
result += num;
|
|
pos += 64;
|
|
}
|
|
assert_eq!(result, F64_RESULT);
|
|
black_box(result)
|
|
}
|
|
|
|
#[library_benchmark]
|
|
#[bench::le(ONES_LE)]
|
|
#[bench::be(ONES_BE)]
|
|
fn perf_bool<E: Endianness>(buffer: BitReadBuffer<E>) {
|
|
let mut pos = 0;
|
|
let len = buffer.bit_len() / 8;
|
|
loop {
|
|
if pos >= len {
|
|
break;
|
|
}
|
|
let num = buffer.read_bool(pos).unwrap();
|
|
black_box(num);
|
|
pos += 1;
|
|
}
|
|
}
|
|
|
|
fn build_string_buffer<E: Endianness>(
|
|
offset: usize,
|
|
endianness: E,
|
|
) -> (usize, BitReadBuffer<'static, E>) {
|
|
let mut data = Vec::new();
|
|
let input = [
|
|
"foo\0",
|
|
"bar\0",
|
|
"something a little bit longer for extra testing\0",
|
|
"a\0",
|
|
"\0",
|
|
]
|
|
.join("");
|
|
let mut writer = BitWriteStream::new(&mut data, endianness);
|
|
writer.write_int(0usize, offset).unwrap();
|
|
while writer.byte_len() < 10 * 1024 {
|
|
writer.write(&input).unwrap()
|
|
}
|
|
(offset, BitReadBuffer::new_owned(data, endianness))
|
|
}
|
|
|
|
#[library_benchmark(setup = build_string_buffer)]
|
|
#[bench::le_alligned(0, LittleEndian)]
|
|
#[bench::be_alligned(0, BigEndian)]
|
|
#[bench::le_unalligned(3, LittleEndian)]
|
|
#[bench::be_unalligned(3, BigEndian)]
|
|
fn perf_string<E: Endianness>((offset, buffer): (usize, BitReadBuffer<E>)) {
|
|
let mut pos = offset;
|
|
let len = buffer.bit_len();
|
|
loop {
|
|
if pos + (128 * 8) > len {
|
|
break;
|
|
}
|
|
let result = buffer.read_string(pos, None).unwrap();
|
|
pos += (result.len() + 1) * 8;
|
|
black_box(result);
|
|
}
|
|
}
|
|
|
|
#[library_benchmark(setup = build_string_buffer)]
|
|
#[bench::le_alligned(0, LittleEndian)]
|
|
#[bench::be_alligned(0, BigEndian)]
|
|
#[bench::le_unalligned(3, LittleEndian)]
|
|
#[bench::be_unalligned(3, BigEndian)]
|
|
fn perf_string_into<E: Endianness>((offset, buffer): (usize, BitReadBuffer<E>)) {
|
|
let mut pos = offset;
|
|
let len = buffer.bit_len();
|
|
let mut buff = String::new();
|
|
loop {
|
|
if pos + (128 * 8) > len {
|
|
break;
|
|
}
|
|
let result = buffer.read_string_into(pos, None, &mut buff).unwrap();
|
|
let result = result.as_ref(&buff);
|
|
pos += (result.len() + 1) * 8;
|
|
black_box(result);
|
|
}
|
|
}
|
|
|
|
#[library_benchmark(setup = build_string_buffer)]
|
|
#[bench::le_alligned(0, LittleEndian)]
|
|
#[bench::be_alligned(0, BigEndian)]
|
|
#[bench::le_unalligned(3, LittleEndian)]
|
|
#[bench::be_unalligned(3, BigEndian)]
|
|
fn perf_bytes<E: Endianness>((offset, buffer): (usize, BitReadBuffer<E>)) {
|
|
let mut pos = offset;
|
|
let len = buffer.bit_len();
|
|
loop {
|
|
if pos + (128 * 8) > len {
|
|
break;
|
|
}
|
|
let result = buffer.read_bytes(pos, 128).unwrap();
|
|
pos += (result.len() + 1) * 8;
|
|
black_box(result);
|
|
}
|
|
}
|
|
|
|
#[library_benchmark(setup = build_string_buffer)]
|
|
#[bench::le_alligned(0, LittleEndian)]
|
|
#[bench::be_alligned(0, BigEndian)]
|
|
#[bench::le_unalligned(3, LittleEndian)]
|
|
#[bench::be_unalligned(3, BigEndian)]
|
|
fn perf_bytes_into<E: Endianness>((offset, buffer): (usize, BitReadBuffer<E>)) {
|
|
let mut pos = offset;
|
|
let len = buffer.bit_len();
|
|
let mut buff = Vec::new();
|
|
loop {
|
|
if pos + (128 * 8) > len {
|
|
break;
|
|
}
|
|
let result = buffer.read_bytes_into(pos, 128, &mut buff).unwrap();
|
|
let result = result.as_ref(&buff);
|
|
pos += (result.len() + 1) * 8;
|
|
black_box(result);
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(BitRead)]
|
|
struct BasicStruct {
|
|
a: f32,
|
|
b: bool,
|
|
#[size = 7]
|
|
c: u32,
|
|
}
|
|
|
|
const BASIC: BasicStruct = BasicStruct {
|
|
a: 0.0,
|
|
b: false,
|
|
c: 0,
|
|
};
|
|
|
|
#[allow(dead_code)]
|
|
#[derive(BitRead)]
|
|
#[discriminant_bits = 2]
|
|
enum BasicEnum {
|
|
#[size = 5]
|
|
Foo(i8),
|
|
Bar(bool),
|
|
Asd(u8),
|
|
Empty,
|
|
}
|
|
|
|
const ENUM: BasicEnum = BasicEnum::Empty;
|
|
|
|
#[library_benchmark]
|
|
#[bench::le(ONES_LE, BASIC)]
|
|
#[bench::be(ONES_BE, BASIC)]
|
|
#[bench::le_enum(ONES_LE, ENUM)]
|
|
#[bench::be_enum(ONES_BE, ENUM)]
|
|
fn perf_struct<E: Endianness, Struct: BitRead<'static, E>>(
|
|
buffer: BitReadBuffer<E>,
|
|
_struct: Struct,
|
|
) {
|
|
let mut stream: BitReadStream<E> = buffer.into();
|
|
while stream.bits_left() > 40 {
|
|
let result = stream.read::<BasicStruct>().unwrap();
|
|
black_box(result);
|
|
}
|
|
}
|
|
|
|
library_benchmark_group!(
|
|
name = bench_read_primitives;
|
|
benchmarks = read_perf, perf_bool, perf_f32, perf_f64
|
|
);
|
|
|
|
library_benchmark_group!(
|
|
name = bench_read_string;
|
|
compare_by_id = true;
|
|
benchmarks = perf_string, perf_string_into
|
|
);
|
|
|
|
library_benchmark_group!(
|
|
name = bench_read_bytes;
|
|
compare_by_id = true;
|
|
benchmarks = perf_bytes, perf_bytes_into
|
|
);
|
|
|
|
library_benchmark_group!(
|
|
name = bench_read_struct;
|
|
benchmarks = perf_struct
|
|
);
|
|
|
|
main!(
|
|
library_benchmark_groups = bench_read_primitives,
|
|
bench_read_string,
|
|
bench_read_bytes,
|
|
bench_read_struct
|
|
);
|