use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use koru_lambda_core::{
Canonicalizable, Distinction, DistinctionEngine, LocalCausalAgent, NetworkAgent,
ParallelAction, ParallelBatchProcessor, ParallelSynthesizer, PeerIdentity, ProcessingStrategy,
StructuralCompactor, TransactionAction, TransactionBatch,
};
use std::sync::Arc;
fn propose_and_finalize_batch(
agent: &mut NetworkAgent,
batch: TransactionBatch,
engine: &Arc<DistinctionEngine>,
) -> Result<Distinction, String> {
let commitment = agent.propose_commitment(batch.clone(), engine)?;
agent.finalize_batch(batch, commitment.commitment_hash, engine)
}
fn bench_core_synthesis(c: &mut Criterion) {
let mut group = c.benchmark_group("core_synthesis");
for size in [100, 1_000, 10_000].iter() {
group.throughput(Throughput::Elements(*size as u64));
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
let engine = Arc::new(DistinctionEngine::new());
b.iter(|| {
let d0 = engine.d0().clone();
let d1 = engine.d1().clone();
let mut current = engine.synthesize(&d0, &d1);
for i in 0..size {
let byte = ((i % 256) as u8).to_canonical_structure(&engine);
current = engine.synthesize(¤t, &byte);
}
black_box(current)
});
});
}
group.finish();
}
fn bench_transaction_validation(c: &mut Criterion) {
let mut group = c.benchmark_group("transaction_validation");
for batch_size in [10, 50, 100].iter() {
group.throughput(Throughput::Elements(*batch_size as u64));
group.bench_with_input(
BenchmarkId::from_parameter(batch_size),
batch_size,
|b, &batch_size| {
let engine = Arc::new(DistinctionEngine::new());
let mut agent = NetworkAgent::new(&engine);
for i in 0..5 {
let peer = PeerIdentity::new(format!("validator_{}", i), &engine);
agent.join_peer(peer, &engine);
}
b.iter(|| {
let transactions: Vec<TransactionAction> = (0..batch_size)
.map(|i| TransactionAction { nonce: i as u64, data: vec![i as u8] })
.collect();
let batch = TransactionBatch {
transactions,
previous_root: agent.consensus_state_root().to_string(),
};
let result = propose_and_finalize_batch(&mut agent, batch, &engine);
black_box(result)
});
},
);
}
group.finish();
}
fn bench_leader_election(c: &mut Criterion) {
let mut group = c.benchmark_group("leader_election");
for num_validators in [5, 10, 20, 50].iter() {
group.bench_with_input(
BenchmarkId::from_parameter(num_validators),
num_validators,
|b, &num_validators| {
let engine = Arc::new(DistinctionEngine::new());
let mut agent = NetworkAgent::new(&engine);
for i in 0..num_validators {
let peer = PeerIdentity::new(format!("validator_{}", i), &engine);
agent.join_peer(peer, &engine);
}
b.iter(|| {
let leader = agent.get_current_leader();
black_box(leader)
});
},
);
}
group.finish();
}
fn bench_compaction(c: &mut Criterion) {
let mut group = c.benchmark_group("compaction");
group.sample_size(10);
for graph_size in [1_000, 5_000, 10_000].iter() {
group.bench_with_input(
BenchmarkId::from_parameter(graph_size),
graph_size,
|b, &graph_size| {
let engine = Arc::new(DistinctionEngine::new());
let d0 = engine.d0().clone();
let d1 = engine.d1().clone();
let mut current = engine.synthesize(&d0, &d1);
for i in 0..graph_size {
let byte = ((i % 256) as u8).to_canonical_structure(&engine);
current = engine.synthesize(¤t, &byte);
}
b.iter(|| {
let mut compactor = StructuralCompactor::new(&engine);
compactor.set_hot_threshold(8);
let action = compactor.compact(&engine);
black_box(action)
});
},
);
}
group.finish();
}
fn bench_distributed_consensus(c: &mut Criterion) {
let mut group = c.benchmark_group("distributed_consensus");
group.sample_size(10);
for num_nodes in [3, 5, 7].iter() {
group.bench_with_input(
BenchmarkId::from_parameter(num_nodes),
num_nodes,
|b, &num_nodes| {
let engine = Arc::new(DistinctionEngine::new());
let mut nodes: Vec<NetworkAgent> =
(0..num_nodes).map(|_| NetworkAgent::new(&engine)).collect();
let validators: Vec<PeerIdentity> = (0..num_nodes)
.map(|i| PeerIdentity::new(format!("node_{}", i), &engine))
.collect();
for node in nodes.iter_mut() {
for validator in validators.iter() {
node.join_peer(validator.clone(), &engine);
}
}
b.iter(|| {
let mut tx_count = 0;
for batch_idx in 0..10 {
let transactions: Vec<TransactionAction> = (0..10)
.map(|i| TransactionAction {
nonce: (batch_idx * 10 + i) as u64,
data: vec![batch_idx as u8, i as u8],
})
.collect();
let batch = TransactionBatch {
transactions: transactions.clone(),
previous_root: nodes[0].consensus_state_root().to_string(),
};
for node in nodes.iter_mut() {
let _ = propose_and_finalize_batch(node, batch.clone(), &engine);
}
tx_count += transactions.len();
for node in nodes.iter_mut() {
node.advance_epoch(&engine);
}
}
black_box(tx_count)
});
},
);
}
group.finish();
}
fn bench_byte_canonicalization(c: &mut Criterion) {
let mut group = c.benchmark_group("byte_canonicalization");
for size in [100, 1_000, 10_000].iter() {
group.throughput(Throughput::Bytes(*size as u64));
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
let engine = Arc::new(DistinctionEngine::new());
let data: Vec<u8> = (0..size).map(|i| (i % 256) as u8).collect();
b.iter(|| {
for &byte in &data {
let d = byte.to_canonical_structure(&engine);
black_box(d);
}
});
});
}
group.finish();
}
fn bench_network_events(c: &mut Criterion) {
let mut group = c.benchmark_group("network_events");
group.bench_function("peer_join", |b| {
let engine = Arc::new(DistinctionEngine::new());
let mut agent = NetworkAgent::new(&engine);
b.iter(|| {
let peer = PeerIdentity::new("test_peer".to_string(), &engine);
agent.join_peer(peer, &engine);
black_box(&agent);
});
});
group.bench_function("epoch_advance", |b| {
let engine = Arc::new(DistinctionEngine::new());
let mut agent = NetworkAgent::new(&engine);
for i in 0..5 {
let peer = PeerIdentity::new(format!("validator_{}", i), &engine);
agent.join_peer(peer, &engine);
}
b.iter(|| {
agent.advance_epoch(&engine);
black_box(&agent);
});
});
group.finish();
}
fn bench_parallel_batch_processing(c: &mut Criterion) {
let mut group = c.benchmark_group("parallel_batch_processing");
for num_batches in [10, 100, 1_000].iter() {
group.throughput(Throughput::Elements(*num_batches as u64));
group.bench_with_input(
BenchmarkId::from_parameter(num_batches),
num_batches,
|b, &num_batches| {
let engine = Arc::new(DistinctionEngine::new());
let mut processor = ParallelBatchProcessor::new(&engine);
b.iter(|| {
let mut current_root = processor.get_current_root().id().to_string();
for i in 0..num_batches {
let batch = TransactionBatch {
transactions: vec![TransactionAction {
nonce: i as u64,
data: vec![i as u8],
}],
previous_root: current_root.clone(),
};
let action = ParallelAction {
batches: vec![batch],
strategy: ProcessingStrategy::Sequential,
};
let new_root = processor.synthesize_action(action, &engine);
current_root = new_root.id().to_string();
}
black_box(processor.batches_processed())
});
},
);
}
group.finish();
}
fn bench_parallel_byte_canonicalization(c: &mut Criterion) {
let mut group = c.benchmark_group("parallel_byte_canon");
for size in [1_000, 10_000, 100_000].iter() {
group.throughput(Throughput::Bytes(*size as u64));
group.bench_with_input(BenchmarkId::new("sequential", size), size, |b, &size| {
let engine = Arc::new(DistinctionEngine::new());
let data: Vec<u8> = (0..size).map(|i| (i % 256) as u8).collect();
b.iter(|| {
let results: Vec<_> = data
.iter()
.map(|&byte| {
let d = byte.to_canonical_structure(&engine);
d.id().to_string()
})
.collect();
black_box(results)
});
});
group.bench_with_input(BenchmarkId::new("parallel", size), size, |b, &size| {
let engine = Arc::new(DistinctionEngine::new());
let synthesizer = ParallelSynthesizer::new(engine.clone());
let data: Vec<u8> = (0..size).map(|i| (i % 256) as u8).collect();
b.iter(|| {
let results = synthesizer.canonicalize_bytes_parallel(data.clone());
black_box(results)
});
});
}
group.finish();
}
fn bench_parallel_synthesis(c: &mut Criterion) {
let mut group = c.benchmark_group("parallel_synthesis");
for num_ops in [100, 1_000, 10_000].iter() {
group.throughput(Throughput::Elements(*num_ops as u64));
group.bench_with_input(BenchmarkId::from_parameter(num_ops), num_ops, |b, &num_ops| {
let engine = Arc::new(DistinctionEngine::new());
let synthesizer = ParallelSynthesizer::new(engine.clone());
let d0_id = engine.d0().id().to_string();
let d1_id = engine.d1().id().to_string();
let pairs: Vec<(String, String)> =
(0..num_ops).map(|_| (d0_id.clone(), d1_id.clone())).collect();
b.iter(|| {
let results = synthesizer.synthesize_parallel(pairs.clone());
black_box(results)
});
});
}
group.finish();
}
fn bench_multi_batch_parallel(c: &mut Criterion) {
let mut group = c.benchmark_group("multi_batch_parallel");
group.sample_size(10);
for batches_per_action in [10, 50, 100].iter() {
group.throughput(Throughput::Elements(*batches_per_action as u64 * 10));
group.bench_with_input(
BenchmarkId::from_parameter(batches_per_action),
batches_per_action,
|b, &batches_per_action| {
let engine = Arc::new(DistinctionEngine::new());
let mut processor = ParallelBatchProcessor::new(&engine);
b.iter(|| {
let initial_root = processor.get_current_root().id().to_string();
let current_root = initial_root.clone();
let batches: Vec<TransactionBatch> = (0..batches_per_action)
.map(|batch_idx| {
let transactions: Vec<TransactionAction> = (0..10)
.map(|tx_idx| TransactionAction {
nonce: (batch_idx * 10 + tx_idx) as u64,
data: vec![batch_idx as u8, tx_idx as u8],
})
.collect();
TransactionBatch {
transactions,
previous_root: if batch_idx == 0 {
current_root.clone()
} else {
String::new() },
}
})
.collect();
let action =
ParallelAction { batches, strategy: ProcessingStrategy::Sequential };
let _new_root = processor.synthesize_action(action, &engine);
black_box(processor.batches_processed())
});
},
);
}
group.finish();
}
criterion_group!(
benches,
bench_core_synthesis,
bench_transaction_validation,
bench_leader_election,
bench_compaction,
bench_distributed_consensus,
bench_byte_canonicalization,
bench_network_events,
bench_parallel_batch_processing,
bench_parallel_byte_canonicalization,
bench_parallel_synthesis,
bench_multi_batch_parallel,
);
criterion_main!(benches);