328 lines
8.9 KiB
Rust
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
|
|
);
|