mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-14 18:32:42 +00:00
Add LRU cache to database (#837)
* Add LRU caches to store * Improvements to LRU caches * Take state by value in `Store::put_state` * Store blocks by value, configurable cache sizes * Use a StateBatch to efficiently store skip states * Fix store tests * Add CloneConfig test, remove unused metrics * Use Mutexes instead of RwLocks for LRU caches
This commit is contained in:
@@ -17,11 +17,13 @@ use tree_hash::TreeHash;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
pub use self::committee_cache::CommitteeCache;
|
||||
pub use clone_config::CloneConfig;
|
||||
pub use eth_spec::*;
|
||||
pub use tree_hash_cache::BeaconTreeHashCache;
|
||||
|
||||
#[macro_use]
|
||||
mod committee_cache;
|
||||
mod clone_config;
|
||||
mod exit_cache;
|
||||
mod pubkey_cache;
|
||||
mod tests;
|
||||
@@ -948,7 +950,8 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clone_without_caches(&self) -> Self {
|
||||
/// Clone the state whilst preserving only the selected caches.
|
||||
pub fn clone_with(&self, config: CloneConfig) -> Self {
|
||||
BeaconState {
|
||||
genesis_time: self.genesis_time,
|
||||
slot: self.slot,
|
||||
@@ -970,21 +973,35 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
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: None,
|
||||
committee_caches: if config.committee_caches {
|
||||
self.committee_caches.clone()
|
||||
} else {
|
||||
[
|
||||
CommitteeCache::default(),
|
||||
CommitteeCache::default(),
|
||||
CommitteeCache::default(),
|
||||
]
|
||||
},
|
||||
pubkey_cache: if config.pubkey_cache {
|
||||
self.pubkey_cache.clone()
|
||||
} else {
|
||||
PubkeyCache::default()
|
||||
},
|
||||
exit_cache: if config.exit_cache {
|
||||
self.exit_cache.clone()
|
||||
} else {
|
||||
ExitCache::default()
|
||||
},
|
||||
tree_hash_cache: if config.tree_hash_cache {
|
||||
self.tree_hash_cache.clone()
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_with_only_committee_caches(&self) -> Self {
|
||||
let mut state = self.clone_without_caches();
|
||||
state.committee_caches = self.committee_caches.clone();
|
||||
state
|
||||
self.clone_with(CloneConfig::committee_caches_only())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
eth2/types/src/beacon_state/clone_config.rs
Normal file
43
eth2/types/src/beacon_state/clone_config.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
/// Configuration struct for controlling which caches of a `BeaconState` should be cloned.
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||
pub struct CloneConfig {
|
||||
pub committee_caches: bool,
|
||||
pub pubkey_cache: bool,
|
||||
pub exit_cache: bool,
|
||||
pub tree_hash_cache: bool,
|
||||
}
|
||||
|
||||
impl CloneConfig {
|
||||
pub fn all() -> Self {
|
||||
Self {
|
||||
committee_caches: true,
|
||||
pubkey_cache: true,
|
||||
exit_cache: true,
|
||||
tree_hash_cache: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn none() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn committee_caches_only() -> Self {
|
||||
Self {
|
||||
committee_caches: true,
|
||||
..Self::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn sanity() {
|
||||
assert!(CloneConfig::all().pubkey_cache);
|
||||
assert!(!CloneConfig::none().tree_hash_cache);
|
||||
assert!(CloneConfig::committee_caches_only().committee_caches);
|
||||
assert!(!CloneConfig::committee_caches_only().exit_cache);
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,75 @@ fn cache_initialization() {
|
||||
test_cache_initialization(&mut state, RelativeEpoch::Next, &spec);
|
||||
}
|
||||
|
||||
fn test_clone_config<E: EthSpec>(base_state: &BeaconState<E>, clone_config: CloneConfig) {
|
||||
let state = base_state.clone_with(clone_config.clone());
|
||||
if clone_config.committee_caches {
|
||||
state
|
||||
.committee_cache(RelativeEpoch::Previous)
|
||||
.expect("committee cache exists");
|
||||
state
|
||||
.committee_cache(RelativeEpoch::Current)
|
||||
.expect("committee cache exists");
|
||||
state
|
||||
.committee_cache(RelativeEpoch::Next)
|
||||
.expect("committee cache exists");
|
||||
} else {
|
||||
state
|
||||
.committee_cache(RelativeEpoch::Previous)
|
||||
.expect_err("shouldn't exist");
|
||||
state
|
||||
.committee_cache(RelativeEpoch::Current)
|
||||
.expect_err("shouldn't exist");
|
||||
state
|
||||
.committee_cache(RelativeEpoch::Next)
|
||||
.expect_err("shouldn't exist");
|
||||
}
|
||||
if clone_config.pubkey_cache {
|
||||
assert_ne!(state.pubkey_cache.len(), 0);
|
||||
} else {
|
||||
assert_eq!(state.pubkey_cache.len(), 0);
|
||||
}
|
||||
if clone_config.exit_cache {
|
||||
state
|
||||
.exit_cache
|
||||
.check_initialized()
|
||||
.expect("exit cache exists");
|
||||
} else {
|
||||
state
|
||||
.exit_cache
|
||||
.check_initialized()
|
||||
.expect_err("exit cache doesn't exist");
|
||||
}
|
||||
if clone_config.tree_hash_cache {
|
||||
assert!(state.tree_hash_cache.is_some());
|
||||
} else {
|
||||
assert!(state.tree_hash_cache.is_none(), "{:?}", clone_config);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_config() {
|
||||
let spec = MinimalEthSpec::default_spec();
|
||||
|
||||
let builder: TestingBeaconStateBuilder<MinimalEthSpec> =
|
||||
TestingBeaconStateBuilder::from_default_keypairs_file_if_exists(16, &spec);
|
||||
let (mut state, _keypairs) = builder.build();
|
||||
|
||||
state.build_all_caches(&spec).unwrap();
|
||||
|
||||
let num_caches = 4;
|
||||
let all_configs = (0..2u8.pow(num_caches)).map(|i| CloneConfig {
|
||||
committee_caches: (i & 1) != 0,
|
||||
pubkey_cache: ((i >> 1) & 1) != 0,
|
||||
exit_cache: ((i >> 2) & 1) != 0,
|
||||
tree_hash_cache: ((i >> 3) & 1) != 0,
|
||||
});
|
||||
|
||||
for config in all_configs {
|
||||
test_clone_config(&state, config);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tree_hash_cache() {
|
||||
use crate::test_utils::{SeedableRng, TestRandom, XorShiftRng};
|
||||
|
||||
Reference in New Issue
Block a user