synor/crates/synor-mining/benches/kheavyhash.rs
2026-01-08 05:22:24 +05:30

328 lines
8.9 KiB
Rust

//! Comprehensive benchmarks for kHeavyHash mining.
//!
//! Benchmarks:
//! - GF(2^8) multiplication tables
//! - Matrix multiplication (standard vs optimized)
//! - kHeavyHash stages (pre-hash, finalize, full)
//! - Mining throughput (single and parallel)
//! - Difficulty validation
//!
//! Run with: cargo bench -p synor-mining
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use synor_mining::kheavyhash::{HashrateBenchmark, KHeavyHash, ParallelMiner};
use synor_mining::matrix::{gf_mul, HeavyMatrix, OptimizedMatrix};
use synor_mining::Target;
// ==================== GF(2^8) Operations ====================
fn bench_gf_mul(c: &mut Criterion) {
c.bench_function("gf_mul_full_table", |b| {
b.iter(|| {
for a in 0..=255u8 {
for bb in 0..=255u8 {
black_box(gf_mul(a, bb));
}
}
})
});
}
fn bench_gf_mul_single(c: &mut Criterion) {
c.bench_function("gf_mul_single", |b| {
let a = 0x53u8;
let bb = 0xCAu8;
b.iter(|| black_box(gf_mul(a, bb)))
});
}
// ==================== Matrix Operations ====================
fn bench_matrix_multiply(c: &mut Criterion) {
let matrix = HeavyMatrix::new();
let input = [0x42u8; 32];
c.bench_function("matrix_multiply_standard", |b| {
b.iter(|| black_box(matrix.multiply(&input)))
});
}
fn bench_optimized_matrix_multiply(c: &mut Criterion) {
let matrix = OptimizedMatrix::new();
let input = [0x42u8; 32];
c.bench_function("matrix_multiply_optimized", |b| {
b.iter(|| black_box(matrix.multiply(&input)))
});
}
fn bench_matrix_creation(c: &mut Criterion) {
c.bench_function("matrix_create_optimized", |b| {
b.iter(|| black_box(OptimizedMatrix::new()))
});
}
fn bench_matrix_from_seed(c: &mut Criterion) {
let seed = [0x42u8; 32];
c.bench_function("matrix_from_seed", |b| {
b.iter(|| black_box(OptimizedMatrix::from_seed(&seed)))
});
}
// ==================== kHeavyHash Core ====================
fn bench_kheavyhash(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let header = [0x42u8; 80];
let mut group = c.benchmark_group("kheavyhash");
group.throughput(Throughput::Elements(1));
// Full hash (header + nonce -> pow_hash)
group.bench_function("full_hash", |b| {
let mut nonce = 0u64;
b.iter(|| {
let result = hasher.hash(&header, nonce);
nonce = nonce.wrapping_add(1);
black_box(result)
})
});
// Pre-hash only (SHA3-256 of header)
group.bench_function("pre_hash_only", |b| {
b.iter(|| black_box(hasher.pre_hash(&header)))
});
// Finalize only (Blake3 + matrix + SHA3 per nonce)
let pre_hash = hasher.pre_hash(&header);
group.bench_function("finalize_only", |b| {
let mut nonce = 0u64;
b.iter(|| {
let result = hasher.finalize(&pre_hash, nonce);
nonce = nonce.wrapping_add(1);
black_box(result)
})
});
group.finish();
}
fn bench_kheavyhash_varying_headers(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let mut group = c.benchmark_group("kheavyhash_header_size");
for size in [32, 64, 80, 128, 256] {
let header = vec![0x42u8; size];
group.throughput(Throughput::Bytes(size as u64));
group.bench_with_input(BenchmarkId::from_parameter(size), &header, |b, h| {
let mut nonce = 0u64;
b.iter(|| {
let result = hasher.hash(h, nonce);
nonce = nonce.wrapping_add(1);
black_box(result)
})
});
}
group.finish();
}
// ==================== Mining Throughput ====================
fn bench_mining_throughput(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let header = [0x42u8; 80];
let pre_hash = hasher.pre_hash(&header);
let mut group = c.benchmark_group("mining_throughput");
for count in [100, 1000, 10000] {
group.throughput(Throughput::Elements(count));
group.bench_with_input(BenchmarkId::from_parameter(count), &count, |b, &count| {
b.iter(|| {
for nonce in 0..count {
black_box(hasher.finalize(&pre_hash, nonce));
}
})
});
}
group.finish();
}
fn bench_mining_with_target(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let header = [0x42u8; 80];
let target = Target::max(); // Easy target for benchmarking
let mut group = c.benchmark_group("mining_with_target");
group.throughput(Throughput::Elements(1));
group.bench_function("mine_easy_target", |b| {
b.iter_batched(
|| 0u64,
|start_nonce| black_box(hasher.mine(&header, &target, start_nonce, 10000)),
criterion::BatchSize::SmallInput,
)
});
group.finish();
}
// ==================== Target Validation ====================
fn bench_target_validation(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let header = [0x42u8; 80];
let pre_hash = hasher.pre_hash(&header);
let pow = hasher.finalize(&pre_hash, 12345);
let target = Target::max();
c.bench_function("target_is_met_by", |b| {
b.iter(|| black_box(target.is_met_by(&pow.hash)))
});
}
fn bench_pow_meets_target(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let header = [0x42u8; 80];
let target = Target::max();
// Find a valid nonce first
let pow = hasher.mine(&header, &target, 0, 10000).unwrap();
c.bench_function("pow_meets_target", |b| {
b.iter(|| black_box(pow.meets_target(&target)))
});
}
// ==================== Parallel Mining ====================
fn bench_parallel_miner_creation(c: &mut Criterion) {
let mut group = c.benchmark_group("parallel_miner_create");
for threads in [1, 2, 4, 8] {
group.bench_with_input(BenchmarkId::from_parameter(threads), &threads, |b, &t| {
b.iter(|| black_box(ParallelMiner::new(t)))
});
}
group.finish();
}
fn bench_hashrate_measurement(c: &mut Criterion) {
c.bench_function("hashrate_benchmark_100ms", |b| {
let bench = HashrateBenchmark::new();
b.iter(|| black_box(bench.run(100)))
});
}
// ==================== Hasher Creation ====================
fn bench_hasher_creation(c: &mut Criterion) {
c.bench_function("kheavyhash_new", |b| {
b.iter(|| black_box(KHeavyHash::new()))
});
c.bench_function("kheavyhash_with_seed", |b| {
let seed = [0x42u8; 32];
b.iter(|| black_box(KHeavyHash::with_seed(&seed)))
});
}
// ==================== Verification ====================
fn bench_verify(c: &mut Criterion) {
let hasher = KHeavyHash::new();
let header = [0x42u8; 80];
let target = Target::max();
// Find a valid nonce
let pow = hasher.mine(&header, &target, 0, 10000).unwrap();
c.bench_function("verify_pow", |b| {
b.iter(|| black_box(hasher.verify(&header, pow.nonce, &target)))
});
}
// ==================== Memory Comparison ====================
fn bench_matrix_memory(c: &mut Criterion) {
// This measures the cost of matrix operations with different input patterns
let matrix = OptimizedMatrix::new();
let mut group = c.benchmark_group("matrix_input_patterns");
// Zero input
let zero_input = [0u8; 32];
group.bench_function("zeros", |b| {
b.iter(|| black_box(matrix.multiply(&zero_input)))
});
// All ones
let ones_input = [0xFFu8; 32];
group.bench_function("ones", |b| {
b.iter(|| black_box(matrix.multiply(&ones_input)))
});
// Random pattern
let random_input: [u8; 32] = {
let mut arr = [0u8; 32];
for (i, byte) in arr.iter_mut().enumerate() {
*byte = (i as u8).wrapping_mul(17).wrapping_add(31);
}
arr
};
group.bench_function("random", |b| {
b.iter(|| black_box(matrix.multiply(&random_input)))
});
group.finish();
}
// ==================== Criterion Groups ====================
criterion_group!(gf_benches, bench_gf_mul, bench_gf_mul_single,);
criterion_group!(
matrix_benches,
bench_matrix_multiply,
bench_optimized_matrix_multiply,
bench_matrix_creation,
bench_matrix_from_seed,
bench_matrix_memory,
);
criterion_group!(
kheavyhash_benches,
bench_kheavyhash,
bench_kheavyhash_varying_headers,
bench_hasher_creation,
);
criterion_group!(
mining_benches,
bench_mining_throughput,
bench_mining_with_target,
bench_hashrate_measurement,
);
criterion_group!(
validation_benches,
bench_target_validation,
bench_pow_meets_target,
bench_verify,
);
criterion_group!(parallel_benches, bench_parallel_miner_creation,);
criterion_main!(
gf_benches,
matrix_benches,
kheavyhash_benches,
mining_benches,
validation_benches,
parallel_benches
);