use clock_hash::{estimate_memory_usage, ClockHasher, clockhash256};
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use std::hint::black_box;
fn bench_memory_usage_estimation(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_usage_estimation");
let sizes = [0, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576];
for &size in &sizes {
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_bytes", size)),
&size,
|b, &size| {
b.iter(|| {
let estimated = estimate_memory_usage(black_box(size));
black_box(estimated);
});
},
);
}
group.finish();
}
fn bench_hasher_construction_memory(c: &mut Criterion) {
let mut group = c.benchmark_group("hasher_construction_memory");
let iterations = [1, 10, 100, 1000];
for &iter in &iterations {
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_hashers", iter)),
&iter,
|b, &iter| {
b.iter(|| {
let mut hashers = Vec::with_capacity(iter);
for _ in 0..iter {
hashers.push(ClockHasher::new());
}
black_box(hashers);
});
},
);
}
group.finish();
}
fn bench_incremental_hashing_memory(c: &mut Criterion) {
let mut group = c.benchmark_group("incremental_hashing_memory");
let chunk_sizes = [64, 256, 1024, 4096];
let total_size = 65536;
for &chunk_size in &chunk_sizes {
let data = vec![0x42u8; total_size];
let chunks: Vec<&[u8]> = data.chunks(chunk_size).collect();
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_byte_chunks", chunk_size)),
&chunks,
|b, chunks| {
b.iter(|| {
let mut hasher = ClockHasher::new();
for chunk in chunks.iter() {
hasher.update(black_box(chunk));
}
let hash = hasher.finalize();
black_box(hash);
});
},
);
}
group.finish();
}
fn bench_memory_bandwidth(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_bandwidth");
let sizes = [4096, 16384, 65536, 262144, 1048576];
for &size in &sizes {
let data = vec![0x42u8; size];
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_bytes_bandwidth", size)),
&data,
|b, data| {
b.iter(|| {
let hash = clockhash256(black_box(data));
black_box(hash);
});
},
);
}
group.finish();
}
fn bench_cache_effects(c: &mut Criterion) {
let mut group = c.benchmark_group("cache_effects");
let cache_sizes = [
("l1_cache", 4096), ("l2_cache", 262144), ("l3_cache", 8388608), ("memory", 33554432), ];
for (cache_level, size) in &cache_sizes {
let data = vec![0x42u8; *size];
group.bench_with_input(
BenchmarkId::from_parameter(format!("{}_{}_bytes", cache_level, size)),
&data,
|b, data| {
b.iter(|| {
let hash = clockhash256(black_box(data));
black_box(hash);
});
},
);
}
group.finish();
}
fn bench_allocation_patterns(c: &mut Criterion) {
let mut group = c.benchmark_group("allocation_patterns");
group.bench_function("single_large_allocation", |b| {
b.iter(|| {
let data = vec![0x42u8; 1048576]; let hash = clockhash256(black_box(&data));
black_box(hash);
});
});
group.bench_function("multiple_small_allocations", |b| {
b.iter(|| {
let mut hashes = Vec::new();
for i in 0..16 {
let data = vec![(i as u8); 65536]; let hash = clockhash256(black_box(&data));
hashes.push(hash);
}
black_box(hashes);
});
});
group.bench_function("incremental_allocation", |b| {
b.iter(|| {
let mut hasher = ClockHasher::new();
let chunk_size = 4096;
let total_size = 1048576;
for i in 0..(total_size / chunk_size) {
let chunk = vec![(i as u8); chunk_size];
hasher.update(black_box(&chunk));
}
let hash = hasher.finalize();
black_box(hash);
});
});
group.finish();
}
fn bench_stack_vs_heap(c: &mut Criterion) {
let mut group = c.benchmark_group("stack_vs_heap");
group.bench_function("stack_allocated_small", |b| {
b.iter(|| {
let data = [0x42u8; 1024]; let hash = clockhash256(black_box(&data));
black_box(hash);
});
});
group.bench_function("heap_allocated_small", |b| {
b.iter(|| {
let data = vec![0x42u8; 1024]; let hash = clockhash256(black_box(&data));
black_box(hash);
});
});
group.bench_function("large_data_heap", |b| {
b.iter(|| {
let data = vec![0x42u8; 1048576]; let hash = clockhash256(black_box(&data));
black_box(hash);
});
});
group.finish();
}
fn bench_memory_copy_overhead(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_copy_overhead");
let sizes = [1024, 4096, 16384, 65536];
for &size in &sizes {
group.bench_with_input(
BenchmarkId::from_parameter(format!("direct_{}_bytes", size)),
&size,
|b, &size| {
b.iter(|| {
let data = vec![0x42u8; size];
let hash = clockhash256(black_box(&data));
black_box(hash);
});
},
);
group.bench_with_input(
BenchmarkId::from_parameter(format!("copy_{}_bytes", size)),
&size,
|b, &size| {
b.iter(|| {
let data = vec![0x42u8; size];
let copy = data.clone(); let hash = clockhash256(black_box(©));
black_box(hash);
});
},
);
group.bench_with_input(
BenchmarkId::from_parameter(format!("multiple_copies_{}_bytes", size)),
&size,
|b, &size| {
b.iter(|| {
let mut data = vec![0x42u8; size];
for i in 0..3 {
data.copy_from_slice(&vec![(i as u8); size]); }
let hash = clockhash256(black_box(&data));
black_box(hash);
});
},
);
}
group.finish();
}
fn bench_memory_fragmentation(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_fragmentation");
let iterations = [10, 50, 100];
for &iter in &iterations {
group.bench_with_input(
BenchmarkId::from_parameter(format!("fragmented_{}_iterations", iter)),
&iter,
|b, &iter| {
b.iter(|| {
let mut results = Vec::new();
for i in 0..iter {
let size = 1024 + (i % 10) * 512; let data = vec![(i as u8); size];
let hash = clockhash256(black_box(&data));
results.push(hash);
}
black_box(results);
});
},
);
group.bench_with_input(
BenchmarkId::from_parameter(format!("uniform_{}_iterations", iter)),
&iter,
|b, &iter| {
b.iter(|| {
let mut results = Vec::new();
for i in 0..iter {
let data = vec![(i as u8); 4096]; let hash = clockhash256(black_box(&data));
results.push(hash);
}
black_box(results);
});
},
);
}
group.finish();
}
fn bench_memory_access_patterns(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_access_patterns");
let size = 262144;
group.bench_function("sequential_access", |b| {
b.iter(|| {
let data = vec![0x42u8; size];
let hash = clockhash256(black_box(&data));
black_box(hash);
});
});
let strides = [2, 4, 8, 16];
for &stride in &strides {
group.bench_with_input(
BenchmarkId::from_parameter(format!("stride_{}", stride)),
&stride,
|b, &stride| {
b.iter(|| {
let mut data = vec![0x42u8; size];
for i in (0..size).step_by(stride) {
data[i] = (i % 256) as u8;
}
let hash = clockhash256(black_box(&data));
black_box(hash);
});
},
);
}
group.bench_function("random_access_pattern", |b| {
b.iter(|| {
let mut data = vec![0x42u8; size];
let mut idx = 0usize;
for i in 0..(size / 16) {
idx = (idx.wrapping_mul(1103515245).wrapping_add(12345)) % size;
for j in 0..16 {
if idx + j < size {
data[idx + j] = (i % 256) as u8;
}
}
}
let hash = clockhash256(black_box(&data));
black_box(hash);
});
});
group.finish();
}
fn bench_bulk_memory_usage(c: &mut Criterion) {
let mut group = c.benchmark_group("bulk_memory_usage");
let batch_sizes = [10, 100, 1000];
for &batch_size in &batch_sizes {
let data_size = 4096;
group.bench_with_input(
BenchmarkId::from_parameter(format!("bulk_{}_hashes", batch_size)),
&batch_size,
|b, &batch_size| {
b.iter(|| {
let mut hashes = Vec::with_capacity(batch_size);
for i in 0..batch_size {
let data = vec![(i as u8); data_size];
let hash = clockhash256(black_box(&data));
hashes.push(hash);
}
black_box(hashes);
});
},
);
}
group.finish();
}
criterion_group!(
benches,
bench_memory_usage_estimation,
bench_hasher_construction_memory,
bench_incremental_hashing_memory,
bench_memory_bandwidth,
bench_cache_effects,
bench_allocation_patterns,
bench_stack_vs_heap,
bench_memory_copy_overhead,
bench_memory_fragmentation,
bench_memory_access_patterns,
bench_bulk_memory_usage,
);
criterion_main!(benches);