forked from solana-labs/solana
-
Notifications
You must be signed in to change notification settings - Fork 331
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
caches epoch specific info which stay fixed throughout epoch
Gossip repeatedly locks bank-forks to read epoch stakes, epoch duration or active features, all of which stay fixed throughout the epoch and only change at epoch boundaries. https://github.com/anza-xyz/agave/blob/4d0fc227d/gossip/src/cluster_info.rs#L1562 https://github.com/anza-xyz/agave/blob/4d0fc227d/gossip/src/cluster_info.rs#L2369 https://github.com/anza-xyz/agave/blob/4d0fc227d/gossip/src/cluster_info.rs#L2525 The commit instead implements a cache which refreshes only if the root bank has moved to a new epoch.
- Loading branch information
1 parent
981c4c1
commit 25d4097
Showing
4 changed files
with
161 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
use { | ||
solana_runtime::{ | ||
bank::Bank, | ||
bank_forks::{BankForks, ReadOnlyAtomicSlot}, | ||
}, | ||
solana_sdk::{ | ||
clock::{Epoch, DEFAULT_MS_PER_SLOT}, | ||
epoch_schedule::EpochSchedule, | ||
pubkey::Pubkey, | ||
}, | ||
std::{ | ||
collections::HashMap, | ||
sync::{Arc, RwLock}, | ||
time::Duration, | ||
}, | ||
}; | ||
|
||
// Caches epoch specific information which stay fixed throughout the epoch. | ||
// Refreshes only if the root bank has moved to a new epoch. | ||
pub(crate) struct EpochSpecs { | ||
epoch: Epoch, // when fields were last updated. | ||
epoch_schedule: EpochSchedule, | ||
root: ReadOnlyAtomicSlot, // updated by bank-forks. | ||
bank_forks: Arc<RwLock<BankForks>>, | ||
current_epoch_staked_nodes: Arc<HashMap<Pubkey, /*stake:*/ u64>>, | ||
epoch_duration: Duration, | ||
} | ||
|
||
impl EpochSpecs { | ||
#[inline] | ||
pub(crate) fn current_epoch_staked_nodes(&mut self) -> &Arc<HashMap<Pubkey, /*stake:*/ u64>> { | ||
self.maybe_refresh(); | ||
&self.current_epoch_staked_nodes | ||
} | ||
|
||
#[inline] | ||
pub(crate) fn epoch_duration(&mut self) -> Duration { | ||
self.maybe_refresh(); | ||
self.epoch_duration | ||
} | ||
|
||
// Updates fields if root bank has moved to a new epoch. | ||
fn maybe_refresh(&mut self) { | ||
if self.epoch_schedule.get_epoch(self.root.get()) == self.epoch { | ||
return; // still same epoch. nothing to update. | ||
} | ||
let root_bank = self.bank_forks.read().unwrap().root_bank(); | ||
debug_assert_eq!( | ||
self.epoch_schedule.get_epoch(root_bank.slot()), | ||
root_bank.epoch() | ||
); | ||
self.epoch = root_bank.epoch(); | ||
self.epoch_schedule = root_bank.epoch_schedule().clone(); | ||
self.current_epoch_staked_nodes = root_bank.current_epoch_staked_nodes(); | ||
self.epoch_duration = get_epoch_duration(&root_bank); | ||
} | ||
} | ||
|
||
impl From<Arc<RwLock<BankForks>>> for EpochSpecs { | ||
fn from(bank_forks: Arc<RwLock<BankForks>>) -> Self { | ||
let (root, root_bank) = { | ||
let bank_forks = bank_forks.read().unwrap(); | ||
(bank_forks.get_atomic_root(), bank_forks.root_bank()) | ||
}; | ||
Self { | ||
epoch: root_bank.epoch(), | ||
epoch_schedule: root_bank.epoch_schedule().clone(), | ||
root, | ||
bank_forks, | ||
current_epoch_staked_nodes: root_bank.current_epoch_staked_nodes(), | ||
epoch_duration: get_epoch_duration(&root_bank), | ||
} | ||
} | ||
} | ||
|
||
fn get_epoch_duration(bank: &Bank) -> Duration { | ||
let num_slots = bank.get_slots_in_epoch(bank.epoch()); | ||
Duration::from_millis(num_slots * DEFAULT_MS_PER_SLOT) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use { | ||
super::*, | ||
solana_runtime::genesis_utils::{create_genesis_config, GenesisConfigInfo}, | ||
}; | ||
|
||
#[test] | ||
fn test_get_epoch_duration() { | ||
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000); | ||
let mut bank = Bank::new_for_tests(&genesis_config); | ||
let epoch = 0; | ||
let num_slots = 32; | ||
assert_eq!(bank.epoch(), epoch); | ||
assert_eq!(bank.get_slots_in_epoch(epoch), num_slots); | ||
assert_eq!( | ||
get_epoch_duration(&bank), | ||
Duration::from_millis(num_slots * 400) | ||
); | ||
for slot in 1..32 { | ||
bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::new_unique(), slot); | ||
assert_eq!(bank.epoch(), epoch); | ||
assert_eq!(bank.get_slots_in_epoch(epoch), num_slots); | ||
assert_eq!( | ||
get_epoch_duration(&bank), | ||
Duration::from_millis(num_slots * 400) | ||
); | ||
} | ||
let epoch = 1; | ||
let num_slots = 64; | ||
for slot in 32..32 + num_slots { | ||
bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::new_unique(), slot); | ||
assert_eq!(bank.epoch(), epoch); | ||
assert_eq!(bank.get_slots_in_epoch(epoch), num_slots); | ||
assert_eq!( | ||
get_epoch_duration(&bank), | ||
Duration::from_millis(num_slots * 400) | ||
); | ||
} | ||
let epoch = 2; | ||
let num_slots = 128; | ||
for slot in 96..96 + num_slots { | ||
bank = Bank::new_from_parent(Arc::new(bank), &Pubkey::new_unique(), slot); | ||
assert_eq!(bank.epoch(), epoch); | ||
assert_eq!(bank.get_slots_in_epoch(epoch), num_slots); | ||
assert_eq!( | ||
get_epoch_duration(&bank), | ||
Duration::from_millis(num_slots * 400) | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters