7396cd2cab
* Clippy account manager * Clippy account_manager * Clippy beacon_node/beacon_chain * Clippy beacon_node/client * Clippy beacon_node/eth1 * Clippy beacon_node/eth2-libp2p * Clippy beacon_node/genesis * Clippy beacon_node/network * Clippy beacon_node/rest_api * Clippy beacon_node/src * Clippy beacon_node/store * Clippy eth2/lmd_ghost * Clippy eth2/operation_pool * Clippy eth2/state_processing * Clippy eth2/types * Clippy eth2/utils/bls * Clippy eth2/utils/cahced_tree_hash * Clippy eth2/utils/deposit_contract * Clippy eth2/utils/eth2_interop_keypairs * Clippy eth2/utils/eth2_testnet_config * Clippy eth2/utils/lighthouse_metrics * Clippy eth2/utils/ssz * Clippy eth2/utils/ssz_types * Clippy eth2/utils/tree_hash_derive * Clippy lcli * Clippy tests/beacon_chain_sim * Clippy validator_client * Cargo fmt
420 lines
14 KiB
Rust
420 lines
14 KiB
Rust
extern crate env_logger;
|
|
|
|
use criterion::Criterion;
|
|
use criterion::{black_box, criterion_group, criterion_main, Benchmark};
|
|
use ssz::Encode;
|
|
use state_processing::{test_utils::BlockBuilder, BlockSignatureStrategy, VerifySignatures};
|
|
use types::{BeaconBlock, BeaconState, ChainSpec, EthSpec, MainnetEthSpec, MinimalEthSpec, Slot};
|
|
|
|
pub const VALIDATORS_LOW: usize = 32_768;
|
|
pub const VALIDATORS_HIGH: usize = 300_032;
|
|
|
|
fn all_benches(c: &mut Criterion) {
|
|
env_logger::init();
|
|
|
|
average_bench::<MinimalEthSpec>(c, "minimal", VALIDATORS_LOW);
|
|
average_bench::<MainnetEthSpec>(c, "mainnet", VALIDATORS_LOW);
|
|
average_bench::<MainnetEthSpec>(c, "mainnet", VALIDATORS_HIGH);
|
|
|
|
worst_bench::<MinimalEthSpec>(c, "minimal", VALIDATORS_LOW);
|
|
worst_bench::<MainnetEthSpec>(c, "mainnet", VALIDATORS_LOW);
|
|
worst_bench::<MainnetEthSpec>(c, "mainnet", VALIDATORS_HIGH);
|
|
}
|
|
|
|
/// Run a bench with a average complexity block.
|
|
fn average_bench<T: EthSpec>(c: &mut Criterion, spec_desc: &str, validator_count: usize) {
|
|
let spec = &T::default_spec();
|
|
|
|
let (block, state) = get_average_block(validator_count, spec);
|
|
bench_block::<T>(c, block, state, spec, spec_desc, "average_complexity_block");
|
|
}
|
|
|
|
/// Run a bench with a highly complex block.
|
|
fn worst_bench<T: EthSpec>(c: &mut Criterion, spec_desc: &str, validator_count: usize) {
|
|
let mut spec = &mut T::default_spec();
|
|
|
|
// Allows the exits to be processed sucessfully.
|
|
spec.persistent_committee_period = 0;
|
|
|
|
let (block, state) = get_worst_block(validator_count, spec);
|
|
bench_block::<T>(c, block, state, spec, spec_desc, "high_complexity_block");
|
|
}
|
|
|
|
/// Return a block and state where the block has "average" complexity. I.e., the number of
|
|
/// operations we'd generally expect to see.
|
|
fn get_average_block<T: EthSpec>(
|
|
validator_count: usize,
|
|
spec: &ChainSpec,
|
|
) -> (BeaconBlock<T>, BeaconState<T>) {
|
|
let mut builder: BlockBuilder<T> = BlockBuilder::new(validator_count, &spec);
|
|
// builder.num_attestations = T::MaxAttestations::to_usize();
|
|
builder.num_attestations = 16;
|
|
builder.set_slot(Slot::from(T::slots_per_epoch() * 3 - 2));
|
|
builder.build_caches(&spec);
|
|
builder.build(&spec)
|
|
}
|
|
|
|
/// Return a block and state where the block has the "worst" complexity. The block is not
|
|
/// _guaranteed_ to be the worst possible complexity, it just has the max possible operations.
|
|
fn get_worst_block<T: EthSpec>(
|
|
validator_count: usize,
|
|
spec: &ChainSpec,
|
|
) -> (BeaconBlock<T>, BeaconState<T>) {
|
|
let mut builder: BlockBuilder<T> = BlockBuilder::new(validator_count, &spec);
|
|
builder.maximize_block_operations();
|
|
|
|
// FIXME: enable deposits once we can generate them with valid proofs.
|
|
builder.num_deposits = 0;
|
|
|
|
builder.set_slot(Slot::from(T::slots_per_epoch() * 3 - 2));
|
|
builder.build_caches(&spec);
|
|
builder.build(&spec)
|
|
}
|
|
|
|
#[allow(clippy::unit_arg)]
|
|
fn bench_block<T: EthSpec>(
|
|
c: &mut Criterion,
|
|
block: BeaconBlock<T>,
|
|
state: BeaconState<T>,
|
|
spec: &ChainSpec,
|
|
spec_desc: &str,
|
|
block_desc: &str,
|
|
) {
|
|
let validator_count = state.validators.len();
|
|
|
|
let title = &format!(
|
|
"{}/{}_validators/{}",
|
|
spec_desc, validator_count, block_desc
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new(
|
|
"per_block_processing/individual_signature_verification",
|
|
move |b| {
|
|
b.iter_batched_ref(
|
|
|| (local_spec.clone(), local_state.clone(), local_block.clone()),
|
|
|(spec, ref mut state, block)| {
|
|
black_box(
|
|
state_processing::per_block_processing::<T>(
|
|
state,
|
|
&block,
|
|
None,
|
|
BlockSignatureStrategy::VerifyIndividual,
|
|
&spec,
|
|
)
|
|
.expect("block processing should succeed"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
},
|
|
)
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new(
|
|
"per_block_processing/bulk_signature_verification",
|
|
move |b| {
|
|
b.iter_batched_ref(
|
|
|| (local_spec.clone(), local_state.clone(), local_block.clone()),
|
|
|(spec, ref mut state, block)| {
|
|
black_box(
|
|
state_processing::per_block_processing::<T>(
|
|
state,
|
|
&block,
|
|
None,
|
|
BlockSignatureStrategy::VerifyBulk,
|
|
&spec,
|
|
)
|
|
.expect("block processing should succeed"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
},
|
|
)
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("per_block_processing/no_signature_verification", move |b| {
|
|
b.iter_batched_ref(
|
|
|| (local_spec.clone(), local_state.clone(), local_block.clone()),
|
|
|(spec, ref mut state, block)| {
|
|
black_box(
|
|
state_processing::per_block_processing::<T>(
|
|
state,
|
|
&block,
|
|
None,
|
|
BlockSignatureStrategy::NoVerification,
|
|
&spec,
|
|
)
|
|
.expect("block processing should succeed"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("process_block_header", move |b| {
|
|
b.iter_batched_ref(
|
|
|| (local_spec.clone(), local_state.clone(), local_block.clone()),
|
|
|(spec, ref mut state, block)| {
|
|
black_box(
|
|
state_processing::per_block_processing::process_block_header::<T>(
|
|
state,
|
|
&block,
|
|
None,
|
|
VerifySignatures::True,
|
|
&spec,
|
|
)
|
|
.expect("process_block_header should succeed"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("verify_block_signature", move |b| {
|
|
b.iter_batched_ref(
|
|
|| (local_spec.clone(), local_state.clone(), local_block.clone()),
|
|
|(spec, ref mut state, block)| {
|
|
black_box(
|
|
state_processing::per_block_processing::verify_block_signature::<T>(
|
|
state, &block, None, &spec,
|
|
)
|
|
.expect("verify_block_signature should succeed"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("process_attestations", move |b| {
|
|
b.iter_batched_ref(
|
|
|| (local_spec.clone(), local_state.clone(), local_block.clone()),
|
|
|(spec, ref mut state, block)| {
|
|
black_box(
|
|
state_processing::per_block_processing::process_attestations::<T>(
|
|
state,
|
|
&block.body.attestations,
|
|
VerifySignatures::True,
|
|
&spec,
|
|
)
|
|
.expect("attestation processing should succeed"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("verify_attestation", move |b| {
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let attestation = &local_block.body.attestations[0];
|
|
|
|
(local_spec.clone(), local_state.clone(), attestation.clone())
|
|
},
|
|
|(spec, ref mut state, attestation)| {
|
|
black_box(
|
|
state_processing::per_block_processing::verify_attestation_for_block_inclusion(
|
|
state,
|
|
&attestation,
|
|
VerifySignatures::True,
|
|
spec,
|
|
)
|
|
.expect("should verify attestation"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("get_indexed_attestation", move |b| {
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let attestation = &local_block.body.attestations[0];
|
|
|
|
(local_state.clone(), attestation.clone())
|
|
},
|
|
|(ref mut state, attestation)| {
|
|
black_box(
|
|
state_processing::common::get_indexed_attestation(state, &attestation)
|
|
.expect("should get indexed attestation"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("is_valid_indexed_attestation_with_signature", move |b| {
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let attestation = &local_block.body.attestations[0];
|
|
let indexed_attestation = state_processing::common::get_indexed_attestation(
|
|
&local_state,
|
|
&attestation,
|
|
)
|
|
.expect("should get indexed attestation");
|
|
|
|
(local_spec.clone(), local_state.clone(), indexed_attestation)
|
|
},
|
|
|(spec, ref mut state, indexed_attestation)| {
|
|
black_box(
|
|
state_processing::per_block_processing::is_valid_indexed_attestation(
|
|
state,
|
|
&indexed_attestation,
|
|
VerifySignatures::True,
|
|
spec,
|
|
)
|
|
.expect("should run is_valid_indexed_attestation"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state.clone();
|
|
let local_spec = spec.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("is_valid_indexed_attestation_without_signature", move |b| {
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let attestation = &local_block.body.attestations[0];
|
|
let indexed_attestation = state_processing::common::get_indexed_attestation(
|
|
&local_state,
|
|
&attestation,
|
|
)
|
|
.expect("should get indexed attestation");
|
|
|
|
(local_spec.clone(), local_state.clone(), indexed_attestation)
|
|
},
|
|
|(spec, ref mut state, indexed_attestation)| {
|
|
black_box(
|
|
state_processing::per_block_processing::is_valid_indexed_attestation(
|
|
state,
|
|
&indexed_attestation,
|
|
VerifySignatures::False,
|
|
spec,
|
|
)
|
|
.expect("should run is_valid_indexed_attestation_without_signature"),
|
|
)
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
let local_state = state;
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("get_attesting_indices", move |b| {
|
|
b.iter_batched_ref(
|
|
|| {
|
|
let attestation = &local_block.body.attestations[0];
|
|
|
|
(local_state.clone(), attestation.clone())
|
|
},
|
|
|(ref mut state, attestation)| {
|
|
black_box(state_processing::common::get_attesting_indices(
|
|
state,
|
|
&attestation.data,
|
|
&attestation.aggregation_bits,
|
|
))
|
|
},
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block.clone();
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("ssz_serialize_block", move |b| {
|
|
b.iter_batched_ref(
|
|
|| (),
|
|
|_| black_box(local_block.as_ssz_bytes()),
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
|
|
let local_block = block;
|
|
c.bench(
|
|
&title,
|
|
Benchmark::new("ssz_block_len", move |b| {
|
|
b.iter_batched_ref(
|
|
|| (),
|
|
|_| black_box(local_block.ssz_bytes_len()),
|
|
criterion::BatchSize::SmallInput,
|
|
)
|
|
})
|
|
.sample_size(10),
|
|
);
|
|
}
|
|
|
|
criterion_group!(benches, all_benches,);
|
|
criterion_main!(benches);
|