collects metrics for cached vote/stake accounts consistency
Tracking mismatches between cached vote/stake accounts and accounts-db in preparation of activating feature for updating rewards at epoch-boundary using cached vote/stake accounts.
This commit is contained in:
parent
108aa23d90
commit
d524ae293f
|
@ -172,6 +172,8 @@ struct RewardsMetrics {
|
||||||
calculate_points_us: AtomicU64,
|
calculate_points_us: AtomicU64,
|
||||||
store_stake_accounts_us: AtomicU64,
|
store_stake_accounts_us: AtomicU64,
|
||||||
store_vote_accounts_us: AtomicU64,
|
store_vote_accounts_us: AtomicU64,
|
||||||
|
invalid_cached_vote_accounts: usize,
|
||||||
|
invalid_cached_stake_accounts: usize,
|
||||||
vote_accounts_cache_miss_count: usize,
|
vote_accounts_cache_miss_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1273,6 +1275,8 @@ struct LoadVoteAndStakeAccountsResult {
|
||||||
vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations>,
|
vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations>,
|
||||||
invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
|
invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
|
||||||
invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
|
invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason>,
|
||||||
|
invalid_cached_vote_accounts: usize,
|
||||||
|
invalid_cached_stake_accounts: usize,
|
||||||
vote_accounts_cache_miss_count: usize,
|
vote_accounts_cache_miss_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1846,6 +1850,16 @@ impl Bank {
|
||||||
metrics.store_vote_accounts_us.load(Relaxed),
|
metrics.store_vote_accounts_us.load(Relaxed),
|
||||||
i64
|
i64
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"invalid_cached_vote_accounts",
|
||||||
|
metrics.invalid_cached_vote_accounts,
|
||||||
|
i64
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"invalid_cached_stake_accounts",
|
||||||
|
metrics.invalid_cached_stake_accounts,
|
||||||
|
i64
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"vote_accounts_cache_miss_count",
|
"vote_accounts_cache_miss_count",
|
||||||
metrics.vote_accounts_cache_miss_count,
|
metrics.vote_accounts_cache_miss_count,
|
||||||
|
@ -2639,17 +2653,19 @@ impl Bank {
|
||||||
reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
|
reward_calc_tracer: Option<impl Fn(&RewardCalculationEvent) + Send + Sync>,
|
||||||
) -> LoadVoteAndStakeAccountsResult {
|
) -> LoadVoteAndStakeAccountsResult {
|
||||||
let stakes = self.stakes_cache.stakes();
|
let stakes = self.stakes_cache.stakes();
|
||||||
let vote_with_stake_delegations_map =
|
let cached_vote_accounts = stakes.vote_accounts();
|
||||||
DashMap::with_capacity(stakes.vote_accounts().as_ref().len());
|
let vote_with_stake_delegations_map = DashMap::with_capacity(cached_vote_accounts.len());
|
||||||
let invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
|
let invalid_stake_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
|
||||||
let invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
|
let invalid_vote_keys: DashMap<Pubkey, InvalidCacheEntryReason> = DashMap::new();
|
||||||
|
let invalid_cached_stake_accounts = AtomicUsize::default();
|
||||||
|
let invalid_cached_vote_accounts = AtomicUsize::default();
|
||||||
|
|
||||||
let stake_delegations: Vec<_> = stakes.stake_delegations().iter().collect();
|
let stake_delegations: Vec<_> = stakes.stake_delegations().iter().collect();
|
||||||
thread_pool.install(|| {
|
thread_pool.install(|| {
|
||||||
stake_delegations
|
stake_delegations
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.for_each(|(stake_pubkey, stake_account)| {
|
.for_each(|(stake_pubkey, cached_stake_account)| {
|
||||||
let delegation = stake_account.delegation();
|
let delegation = cached_stake_account.delegation();
|
||||||
let vote_pubkey = &delegation.voter_pubkey;
|
let vote_pubkey = &delegation.voter_pubkey;
|
||||||
if invalid_vote_keys.contains_key(vote_pubkey) {
|
if invalid_vote_keys.contains_key(vote_pubkey) {
|
||||||
return;
|
return;
|
||||||
|
@ -2684,14 +2700,25 @@ impl Bank {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if cached_stake_account != &stake_account {
|
||||||
|
invalid_cached_stake_accounts.fetch_add(1, Relaxed);
|
||||||
|
}
|
||||||
let stake_delegation = (*stake_pubkey, stake_account);
|
let stake_delegation = (*stake_pubkey, stake_account);
|
||||||
let mut vote_delegations = if let Some(vote_delegations) =
|
let mut vote_delegations = if let Some(vote_delegations) =
|
||||||
vote_with_stake_delegations_map.get_mut(vote_pubkey)
|
vote_with_stake_delegations_map.get_mut(vote_pubkey)
|
||||||
{
|
{
|
||||||
vote_delegations
|
vote_delegations
|
||||||
} else {
|
} else {
|
||||||
|
let cached_vote_account = cached_vote_accounts.get(vote_pubkey);
|
||||||
let vote_account = match self.get_account_with_fixed_root(vote_pubkey) {
|
let vote_account = match self.get_account_with_fixed_root(vote_pubkey) {
|
||||||
Some(vote_account) => {
|
Some(vote_account) => {
|
||||||
|
match cached_vote_account {
|
||||||
|
Some((_stake, cached_vote_account))
|
||||||
|
if cached_vote_account == &vote_account => {}
|
||||||
|
_ => {
|
||||||
|
invalid_cached_vote_accounts.fetch_add(1, Relaxed);
|
||||||
|
}
|
||||||
|
};
|
||||||
if vote_account.owner() != &solana_vote_program::id() {
|
if vote_account.owner() != &solana_vote_program::id() {
|
||||||
invalid_vote_keys
|
invalid_vote_keys
|
||||||
.insert(*vote_pubkey, InvalidCacheEntryReason::WrongOwner);
|
.insert(*vote_pubkey, InvalidCacheEntryReason::WrongOwner);
|
||||||
|
@ -2700,6 +2727,9 @@ impl Bank {
|
||||||
vote_account
|
vote_account
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
if cached_vote_account.is_some() {
|
||||||
|
invalid_cached_vote_accounts.fetch_add(1, Relaxed);
|
||||||
|
}
|
||||||
invalid_vote_keys
|
invalid_vote_keys
|
||||||
.insert(*vote_pubkey, InvalidCacheEntryReason::Missing);
|
.insert(*vote_pubkey, InvalidCacheEntryReason::Missing);
|
||||||
return;
|
return;
|
||||||
|
@ -2738,11 +2768,13 @@ impl Bank {
|
||||||
vote_delegations.delegations.push(stake_delegation);
|
vote_delegations.delegations.push(stake_delegation);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
invalid_cached_stake_accounts.fetch_add(invalid_stake_keys.len(), Relaxed);
|
||||||
LoadVoteAndStakeAccountsResult {
|
LoadVoteAndStakeAccountsResult {
|
||||||
vote_with_stake_delegations_map,
|
vote_with_stake_delegations_map,
|
||||||
invalid_vote_keys,
|
invalid_vote_keys,
|
||||||
invalid_stake_keys,
|
invalid_stake_keys,
|
||||||
|
invalid_cached_vote_accounts: invalid_cached_vote_accounts.into_inner(),
|
||||||
|
invalid_cached_stake_accounts: invalid_cached_stake_accounts.into_inner(),
|
||||||
vote_accounts_cache_miss_count: 0,
|
vote_accounts_cache_miss_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2859,6 +2891,8 @@ impl Bank {
|
||||||
vote_with_stake_delegations_map,
|
vote_with_stake_delegations_map,
|
||||||
invalid_vote_keys,
|
invalid_vote_keys,
|
||||||
invalid_stake_keys: DashMap::default(),
|
invalid_stake_keys: DashMap::default(),
|
||||||
|
invalid_cached_vote_accounts: 0,
|
||||||
|
invalid_cached_stake_accounts: 0,
|
||||||
vote_accounts_cache_miss_count: vote_accounts_cache_miss_count.into_inner(),
|
vote_accounts_cache_miss_count: vote_accounts_cache_miss_count.into_inner(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2882,6 +2916,8 @@ impl Bank {
|
||||||
vote_with_stake_delegations_map,
|
vote_with_stake_delegations_map,
|
||||||
invalid_stake_keys,
|
invalid_stake_keys,
|
||||||
invalid_vote_keys,
|
invalid_vote_keys,
|
||||||
|
invalid_cached_vote_accounts,
|
||||||
|
invalid_cached_stake_accounts,
|
||||||
vote_accounts_cache_miss_count,
|
vote_accounts_cache_miss_count,
|
||||||
} = if update_rewards_from_cached_accounts {
|
} = if update_rewards_from_cached_accounts {
|
||||||
self.load_vote_and_stake_accounts(thread_pool, reward_calc_tracer.as_ref())
|
self.load_vote_and_stake_accounts(thread_pool, reward_calc_tracer.as_ref())
|
||||||
|
@ -2895,6 +2931,8 @@ impl Bank {
|
||||||
metrics
|
metrics
|
||||||
.load_vote_and_stake_accounts_us
|
.load_vote_and_stake_accounts_us
|
||||||
.fetch_add(m.as_us(), Relaxed);
|
.fetch_add(m.as_us(), Relaxed);
|
||||||
|
metrics.invalid_cached_vote_accounts += invalid_cached_vote_accounts;
|
||||||
|
metrics.invalid_cached_stake_accounts += invalid_cached_stake_accounts;
|
||||||
metrics.vote_accounts_cache_miss_count += vote_accounts_cache_miss_count;
|
metrics.vote_accounts_cache_miss_count += vote_accounts_cache_miss_count;
|
||||||
let evict_invalid_stakes_cache_entries = self
|
let evict_invalid_stakes_cache_entries = self
|
||||||
.feature_set
|
.feature_set
|
||||||
|
|
|
@ -16,7 +16,7 @@ use {
|
||||||
/// Generic type T enforces type-saftey so that StakeAccount<Delegation> can
|
/// Generic type T enforces type-saftey so that StakeAccount<Delegation> can
|
||||||
/// only wrap a stake-state which is a Delegation; whereas StakeAccount<()>
|
/// only wrap a stake-state which is a Delegation; whereas StakeAccount<()>
|
||||||
/// wraps any account with stake state.
|
/// wraps any account with stake state.
|
||||||
#[derive(Clone, Debug, Default, PartialEq)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct StakeAccount<T> {
|
pub struct StakeAccount<T> {
|
||||||
account: AccountSharedData,
|
account: AccountSharedData,
|
||||||
stake_state: StakeState,
|
stake_state: StakeState,
|
||||||
|
@ -105,6 +105,17 @@ impl<T> From<StakeAccount<T>> for (AccountSharedData, StakeState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S, T> PartialEq<StakeAccount<S>> for StakeAccount<T> {
|
||||||
|
fn eq(&self, other: &StakeAccount<S>) -> bool {
|
||||||
|
let StakeAccount {
|
||||||
|
account,
|
||||||
|
stake_state,
|
||||||
|
_phantom,
|
||||||
|
} = other;
|
||||||
|
account == &self.account && stake_state == &self.stake_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
#[cfg(RUSTC_WITH_SPECIALIZATION)]
|
||||||
impl AbiExample for StakeAccount<Delegation> {
|
impl AbiExample for StakeAccount<Delegation> {
|
||||||
fn example() -> Self {
|
fn example() -> Self {
|
||||||
|
|
|
@ -80,6 +80,10 @@ impl VoteAccount {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VoteAccounts {
|
impl VoteAccounts {
|
||||||
|
pub(crate) fn len(&self) -> usize {
|
||||||
|
self.vote_accounts.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
|
pub fn staked_nodes(&self) -> Arc<HashMap<Pubkey, u64>> {
|
||||||
self.staked_nodes_once.call_once(|| {
|
self.staked_nodes_once.call_once(|| {
|
||||||
let staked_nodes = self
|
let staked_nodes = self
|
||||||
|
@ -238,6 +242,23 @@ impl PartialEq<VoteAccountInner> for VoteAccountInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq<AccountSharedData> for VoteAccount {
|
||||||
|
fn eq(&self, other: &AccountSharedData) -> bool {
|
||||||
|
let Account {
|
||||||
|
lamports,
|
||||||
|
data,
|
||||||
|
owner,
|
||||||
|
executable,
|
||||||
|
rent_epoch,
|
||||||
|
} = &self.0.account;
|
||||||
|
other.lamports() == *lamports
|
||||||
|
&& other.executable() == *executable
|
||||||
|
&& other.rent_epoch() == *rent_epoch
|
||||||
|
&& other.owner() == owner
|
||||||
|
&& other.data() == data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for VoteAccounts {
|
impl Default for VoteAccounts {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
Loading…
Reference in New Issue