use bls::PublicKeyBytes; use criterion::{Criterion, criterion_group, criterion_main}; use rand::Rng; use ssz::Decode; use store::{ StoreConfig, hdiff::{HDiff, HDiffBuffer}, }; use types::{BeaconState, Epoch, Eth1Data, EthSpec, MainnetEthSpec as E, Validator}; pub fn all_benches(c: &mut Criterion) { let spec = E::default_spec(); let genesis_time = 0; let eth1_data = Eth1Data::default(); let mut rng = rand::rng(); let validator_mutations = 1000; let validator_additions = 100; for n in [1_000_000, 1_500_000, 2_000_000] { let mut source_state = BeaconState::::new(genesis_time, eth1_data.clone(), &spec); for _ in 0..n { append_validator(&mut source_state, &mut rng); } let mut target_state = source_state.clone(); // Change all balances for i in 0..n { let balance = target_state.balances_mut().get_mut(i).unwrap(); *balance += rng.random_range(1..=1_000_000); } // And some validator records for _ in 0..validator_mutations { let index = rng.random_range(1..n); // TODO: Only change a few things, and not the pubkey *target_state.validators_mut().get_mut(index).unwrap() = rand_validator(&mut rng); } for _ in 0..validator_additions { append_validator(&mut target_state, &mut rng); } bench_against_states( c, source_state, target_state, &format!("n={n} v_mut={validator_mutations} v_add={validator_additions}"), ); } } fn bench_against_states( c: &mut Criterion, source_state: BeaconState, target_state: BeaconState, id: &str, ) { let slot_diff = target_state.slot() - source_state.slot(); let config = StoreConfig::default(); let source = HDiffBuffer::from_state(source_state); let target = HDiffBuffer::from_state(target_state); let diff = HDiff::compute(&source, &target, &config).unwrap(); println!( "state slot diff {slot_diff} - diff size {id} {}", diff.size() ); c.bench_function(&format!("compute hdiff {id}"), |b| { b.iter(|| { HDiff::compute(&source, &target, &config).unwrap(); }) }); c.bench_function(&format!("apply hdiff {id}"), |b| { b.iter(|| { let mut source = source.clone(); diff.apply(&mut source, &config).unwrap(); }) }); } fn rand_validator(mut rng: impl Rng) -> Validator { let mut pubkey = [0u8; 48]; rng.fill_bytes(&mut pubkey); let withdrawal_credentials: [u8; 32] = rng.random(); Validator { pubkey: PublicKeyBytes::from_ssz_bytes(&pubkey).unwrap(), withdrawal_credentials: withdrawal_credentials.into(), slashed: false, effective_balance: 32_000_000_000, activation_eligibility_epoch: Epoch::max_value(), activation_epoch: Epoch::max_value(), exit_epoch: Epoch::max_value(), withdrawable_epoch: Epoch::max_value(), } } fn append_validator(state: &mut BeaconState, mut rng: impl Rng) { state .balances_mut() .push(32_000_000_000 + rng.random_range(1..=1_000_000_000)) .unwrap(); if let Ok(inactivity_scores) = state.inactivity_scores_mut() { inactivity_scores.push(0).unwrap(); } state .validators_mut() .push(rand_validator(&mut rng)) .unwrap(); } criterion_group! { name = benches; config = Criterion::default().sample_size(10); targets = all_benches } criterion_main!(benches);