Add block/state caching on beacon chain (#677)

* Add basic block/state caching on beacon chain

* Adds checkpoint cache

* Stop storing the tree hash cache in the db

* Remove dedunant beacon state write

* Use caching get methods in fork choice

* Use caching state getting in state_by_slot

* Add state.cacheless_clone

* Attempt to improve attestation processing times

* Introduce HeadInfo struct

* Used cache tree hash for block processing

* Use cached tree hash for block production too
This commit is contained in:
Paul Hauner
2019-12-09 14:20:25 +11:00
committed by GitHub
parent 36624b1d14
commit 2bfc512fb6
8 changed files with 340 additions and 101 deletions

View File

@@ -3,7 +3,7 @@ use criterion::{black_box, criterion_group, criterion_main, Benchmark};
use rayon::prelude::*;
use ssz::{Decode, Encode};
use types::{
test_utils::generate_deterministic_keypair, BeaconState, Eth1Data, EthSpec, Hash256,
test_utils::generate_deterministic_keypair, BeaconState, Epoch, Eth1Data, EthSpec, Hash256,
MainnetEthSpec, Validator,
};
@@ -28,12 +28,12 @@ fn get_state<E: EthSpec>(validator_count: usize) -> BeaconState<E> {
.map(|&i| Validator {
pubkey: generate_deterministic_keypair(i).pk.into(),
withdrawal_credentials: Hash256::from_low_u64_le(i as u64),
effective_balance: i as u64,
slashed: i % 2 == 0,
activation_eligibility_epoch: i.into(),
activation_epoch: i.into(),
exit_epoch: i.into(),
withdrawable_epoch: i.into(),
effective_balance: spec.max_effective_balance,
slashed: false,
activation_eligibility_epoch: Epoch::new(0),
activation_epoch: Epoch::new(0),
exit_epoch: Epoch::from(u64::max_value()),
withdrawable_epoch: Epoch::from(u64::max_value()),
})
.collect::<Vec<_>>()
.into();
@@ -43,14 +43,18 @@ fn get_state<E: EthSpec>(validator_count: usize) -> BeaconState<E> {
fn all_benches(c: &mut Criterion) {
let validator_count = 16_384;
let state = get_state::<MainnetEthSpec>(validator_count);
let spec = &MainnetEthSpec::default_spec();
let mut state = get_state::<MainnetEthSpec>(validator_count);
state.build_all_caches(spec).expect("should build caches");
let state_bytes = state.as_ssz_bytes();
let inner_state = state.clone();
c.bench(
&format!("{}_validators", validator_count),
Benchmark::new("encode/beacon_state", move |b| {
b.iter_batched_ref(
|| state.clone(),
|| inner_state.clone(),
|state| black_box(state.as_ssz_bytes()),
criterion::BatchSize::SmallInput,
)
@@ -73,6 +77,32 @@ fn all_benches(c: &mut Criterion) {
})
.sample_size(10),
);
let inner_state = state.clone();
c.bench(
&format!("{}_validators", validator_count),
Benchmark::new("clone/beacon_state", move |b| {
b.iter_batched_ref(
|| inner_state.clone(),
|state| black_box(state.clone()),
criterion::BatchSize::SmallInput,
)
})
.sample_size(10),
);
let inner_state = state.clone();
c.bench(
&format!("{}_validators", validator_count),
Benchmark::new("clone_without_caches/beacon_state", move |b| {
b.iter_batched_ref(
|| inner_state.clone(),
|state| black_box(state.clone_without_caches()),
criterion::BatchSize::SmallInput,
)
})
.sample_size(10),
);
}
criterion_group!(benches, all_benches,);

View File

@@ -909,6 +909,39 @@ impl<T: EthSpec> BeaconState<T> {
pub fn drop_tree_hash_cache(&mut self) {
self.tree_hash_cache = BeaconTreeHashCache::default();
}
pub fn clone_without_caches(&self) -> Self {
BeaconState {
genesis_time: self.genesis_time,
slot: self.slot,
fork: self.fork.clone(),
latest_block_header: self.latest_block_header.clone(),
block_roots: self.block_roots.clone(),
state_roots: self.state_roots.clone(),
historical_roots: self.historical_roots.clone(),
eth1_data: self.eth1_data.clone(),
eth1_data_votes: self.eth1_data_votes.clone(),
eth1_deposit_index: self.eth1_deposit_index,
validators: self.validators.clone(),
balances: self.balances.clone(),
randao_mixes: self.randao_mixes.clone(),
slashings: self.slashings.clone(),
previous_epoch_attestations: self.previous_epoch_attestations.clone(),
current_epoch_attestations: self.current_epoch_attestations.clone(),
justification_bits: self.justification_bits.clone(),
previous_justified_checkpoint: self.previous_justified_checkpoint.clone(),
current_justified_checkpoint: self.current_justified_checkpoint.clone(),
finalized_checkpoint: self.finalized_checkpoint.clone(),
committee_caches: [
CommitteeCache::default(),
CommitteeCache::default(),
CommitteeCache::default(),
],
pubkey_cache: PubkeyCache::default(),
exit_cache: ExitCache::default(),
tree_hash_cache: BeaconTreeHashCache::default(),
}
}
}
impl From<RelativeEpochError> for Error {