use criterion::{BatchSize, BenchmarkId, Criterion, criterion_group, criterion_main};
use lencode::dedupe::{DedupeDecodeable, DedupeEncodeable, DefaultDedupeHasher};
use lencode::io::{Cursor, VecWriter};
use lencode::pack::Pack;
use lencode::prelude::*;
use std::hint::black_box;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Pack)]
#[repr(transparent)]
struct Key32([u8; 32]);
impl DedupeEncodeable for Key32 {
type Hasher = DefaultDedupeHasher;
}
impl DedupeDecodeable for Key32 {
type Hasher = DefaultDedupeHasher;
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Pack)]
#[repr(transparent)]
struct Key64([u8; 64]);
impl DedupeEncodeable for Key64 {
type Hasher = DefaultDedupeHasher;
}
impl DedupeDecodeable for Key64 {
type Hasher = DefaultDedupeHasher;
}
fn make_key32s(count: usize) -> Vec<Key32> {
use rand::rngs::StdRng;
use rand::{RngExt, SeedableRng};
let mut rng = StdRng::seed_from_u64(0xBAC4);
(0..count).map(|_| Key32(rng.random())).collect()
}
fn make_key64s(count: usize) -> Vec<Key64> {
use rand::rngs::StdRng;
use rand::{RngExt, SeedableRng};
let mut rng = StdRng::seed_from_u64(0xBAC464);
(0..count).map(|_| Key64(rng.random())).collect()
}
fn bench_pack_single(c: &mut Criterion) {
let mut group = c.benchmark_group("pack_single");
let key = Key32([0xCC; 32]);
group.bench_function("key32_pack", |b| {
b.iter_batched(
|| Cursor::new([0u8; 32]),
|cursor| {
let mut cursor = black_box(cursor);
black_box(key.pack(&mut cursor).unwrap());
},
BatchSize::SmallInput,
)
});
let mut enc_buf = [0u8; 32];
key.pack(&mut Cursor::new(&mut enc_buf[..])).unwrap();
group.bench_function("key32_unpack", |b| {
b.iter_batched(
|| Cursor::new(black_box(enc_buf)),
|cursor| {
let mut cursor = black_box(cursor);
black_box(Key32::unpack(&mut cursor).unwrap());
},
BatchSize::SmallInput,
)
});
let key64 = Key64([0xDD; 64]);
group.bench_function("key64_pack", |b| {
b.iter_batched(
|| Cursor::new([0u8; 64]),
|cursor| {
let mut cursor = black_box(cursor);
black_box(key64.pack(&mut cursor).unwrap());
},
BatchSize::SmallInput,
)
});
let val: u64 = 0x123456789ABCDEF0;
group.bench_function("u64_pack", |b| {
b.iter_batched(
|| Cursor::new([0u8; 8]),
|cursor| {
let mut cursor = black_box(cursor);
black_box(val.pack(&mut cursor).unwrap());
},
BatchSize::SmallInput,
)
});
let mut u64_buf = [0u8; 8];
val.pack(&mut Cursor::new(&mut u64_buf[..])).unwrap();
group.bench_function("u64_unpack", |b| {
b.iter_batched(
|| Cursor::new(black_box(u64_buf)),
|cursor| {
let mut cursor = black_box(cursor);
black_box(u64::unpack(&mut cursor).unwrap());
},
BatchSize::SmallInput,
)
});
group.finish();
}
fn bench_pack_bulk(c: &mut Criterion) {
let mut group = c.benchmark_group("pack_bulk");
for &count in &[16usize, 64, 128, 512] {
let keys = make_key32s(count);
let total_bytes = count * 32;
group.bench_with_input(
BenchmarkId::new("key32_pack_slice", count),
&keys,
|b, keys| {
b.iter_batched(
|| VecWriter::with_capacity(total_bytes),
|mut writer| {
let n = Key32::pack_slice(black_box(keys), &mut writer).unwrap();
black_box(n);
},
BatchSize::SmallInput,
)
},
);
let packed = {
let mut w = VecWriter::with_capacity(total_bytes);
Key32::pack_slice(&keys, &mut w).unwrap();
w.into_inner()
};
group.bench_with_input(
BenchmarkId::new("key32_unpack_vec", count),
&packed,
|b, packed| {
b.iter_batched(
|| Cursor::new(packed.as_slice()),
|cursor| {
let mut cursor = black_box(cursor);
let v: Vec<Key32> = Key32::unpack_vec(&mut cursor, count).unwrap();
black_box(v);
},
BatchSize::SmallInput,
)
},
);
}
let keys128 = make_key32s(128);
group.bench_function("key32_pack_loop_128", |b| {
b.iter_batched(
|| VecWriter::with_capacity(128 * 32),
|mut writer| {
for key in black_box(&keys128) {
key.pack(&mut writer).unwrap();
}
black_box(writer);
},
BatchSize::SmallInput,
)
});
let keys64 = make_key64s(128);
group.bench_function("key64_pack_slice_128", |b| {
b.iter_batched(
|| VecWriter::with_capacity(128 * 64),
|mut writer| {
let n = Key64::pack_slice(black_box(&keys64), &mut writer).unwrap();
black_box(n);
},
BatchSize::SmallInput,
)
});
group.finish();
}
fn bench_encode_vs_pack(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_vs_pack");
let keys = make_key32s(128);
group.bench_function("vec_key32_encode_128", |b| {
b.iter_batched(
|| VecWriter::with_capacity(128 * 32 + 16),
|mut writer| {
keys.encode_ext(&mut writer, None).unwrap();
black_box(writer);
},
BatchSize::SmallInput,
)
});
group.bench_function("vec_key32_pack_slice_128", |b| {
b.iter_batched(
|| VecWriter::with_capacity(128 * 32),
|mut writer| {
Key32::pack_slice(black_box(&keys), &mut writer).unwrap();
black_box(writer);
},
BatchSize::SmallInput,
)
});
let encoded = {
let mut w = VecWriter::with_capacity(128 * 32 + 16);
keys.encode_ext(&mut w, None).unwrap();
w.into_inner()
};
group.bench_function("vec_key32_decode_128", |b| {
b.iter_batched(
|| Cursor::new(encoded.as_slice()),
|cursor| {
let mut cursor = black_box(cursor);
let v: Vec<Key32> = Decode::decode_ext(&mut cursor, None).unwrap();
black_box(v);
},
BatchSize::SmallInput,
)
});
group.finish();
}
criterion_group!(
benches,
bench_pack_single,
bench_pack_bulk,
bench_encode_vs_pack
);
criterion_main!(benches);