Cache vote accounts and optimize squash

This commit is contained in:
Sathish Ambley
2019-03-30 18:18:42 -07:00
committed by Greg Fitzgerald
parent cb3adea94f
commit 75ad1305c0

View File

@ -192,6 +192,9 @@ struct ForkInfo {
/// List of all parents of this fork /// List of all parents of this fork
parents: Vec<Fork>, parents: Vec<Fork>,
/// Cached vote accounts
vote_accounts: RwLock<HashMap<Pubkey, Account>>,
} }
// This structure handles the load/store of the accounts // This structure handles the load/store of the accounts
@ -317,21 +320,19 @@ impl AccountsDB {
fn get_vote_accounts_by_fork( fn get_vote_accounts_by_fork(
&self, &self,
fork: Fork, fork: Fork,
account_maps: &HashMap<Fork, AccountMap>, fork_infos: &HashMap<Fork, ForkInfo>,
vote_accounts: &HashMap<Pubkey, Account>, vote_accounts: &HashMap<Pubkey, Account>,
) -> HashMap<Pubkey, Account> { ) -> HashMap<Pubkey, Account> {
account_maps fork_infos
.get(&fork) .get(&fork)
.unwrap() .unwrap()
.vote_accounts
.read() .read()
.unwrap() .unwrap()
.iter() .iter()
.filter_map(|(pubkey, account_info)| { .filter_map(|(pubkey, account)| {
if account_info.is_vote_account && !vote_accounts.contains_key(pubkey) { if !vote_accounts.contains_key(pubkey) {
Some(( Some((*pubkey, account.clone()))
*pubkey,
self.get_account(account_info.id, account_info.offset),
))
} else { } else {
None None
} }
@ -340,16 +341,15 @@ impl AccountsDB {
} }
fn get_vote_accounts(&self, fork: Fork) -> HashMap<Pubkey, Account> { fn get_vote_accounts(&self, fork: Fork) -> HashMap<Pubkey, Account> {
let account_maps = self.account_index.account_maps.read().unwrap();
let mut vote_accounts = HashMap::new(); let mut vote_accounts = HashMap::new();
vote_accounts = self.get_vote_accounts_by_fork(fork, &account_maps, &vote_accounts);
let fork_infos = self.fork_infos.read().unwrap(); let fork_infos = self.fork_infos.read().unwrap();
if let Some(fork_info) = fork_infos.get(&fork) { if let Some(fork_info) = fork_infos.get(&fork) {
vote_accounts = fork_info.vote_accounts.read().unwrap().clone();
for parent_fork in fork_info.parents.iter() { for parent_fork in fork_info.parents.iter() {
for (pubkey, account_info) in let parent_vote_accounts =
self.get_vote_accounts_by_fork(*parent_fork, &account_maps, &vote_accounts) self.get_vote_accounts_by_fork(*parent_fork, &fork_infos, &vote_accounts);
{ for (pubkey, account) in parent_vote_accounts.iter() {
vote_accounts.insert(pubkey, account_info); vote_accounts.insert(*pubkey, account.clone());
} }
} }
} }
@ -574,6 +574,13 @@ impl AccountsDB {
if account.lamports == 0 && self.is_squashed(fork) { if account.lamports == 0 && self.is_squashed(fork) {
// purge if balance is 0 and no checkpoints // purge if balance is 0 and no checkpoints
self.remove_account_entries(fork, &pubkey); self.remove_account_entries(fork, &pubkey);
if solana_vote_api::check_id(&account.owner) {
let fork_infos = self.fork_infos.read().unwrap();
if let Some(fork_info) = fork_infos.get(&fork) {
let mut vote_accounts = fork_info.vote_accounts.write().unwrap();
vote_accounts.remove(pubkey);
}
}
} else { } else {
let (id, offset) = self.append_account(account); let (id, offset) = self.append_account(account);
let account_maps = self.account_index.account_maps.read().unwrap(); let account_maps = self.account_index.account_maps.read().unwrap();
@ -585,6 +592,13 @@ impl AccountsDB {
is_vote_account: solana_vote_api::check_id(&account.owner), is_vote_account: solana_vote_api::check_id(&account.owner),
}; };
self.insert_account_entry(&pubkey, &account_info, &mut account_map); self.insert_account_entry(&pubkey, &account_info, &mut account_map);
if solana_vote_api::check_id(&account.owner) {
let fork_infos = self.fork_infos.read().unwrap();
if let Some(fork_info) = fork_infos.get(&fork) {
let mut vote_accounts = fork_info.vote_accounts.write().unwrap();
vote_accounts.insert(*pubkey, account.clone());
}
}
} }
} }
@ -745,8 +759,12 @@ impl AccountsDB {
} }
fn remove_parents(&self, fork: Fork) -> Vec<Fork> { fn remove_parents(&self, fork: Fork) -> Vec<Fork> {
let mut squashed_vote_accounts = self.get_vote_accounts(fork);
squashed_vote_accounts.retain(|_, account| account.lamports != 0);
let mut info = self.fork_infos.write().unwrap(); let mut info = self.fork_infos.write().unwrap();
let fork_info = info.get_mut(&fork).unwrap(); let fork_info = info.get_mut(&fork).unwrap();
let mut vote_accounts = fork_info.vote_accounts.write().unwrap();
*vote_accounts = squashed_vote_accounts;
fork_info.parents.split_off(0) fork_info.parents.split_off(0)
} }
@ -766,11 +784,28 @@ impl AccountsDB {
let account_maps = self.account_index.account_maps.read().unwrap(); let account_maps = self.account_index.account_maps.read().unwrap();
let mut account_map = account_maps.get(&fork).unwrap().write().unwrap(); let mut account_map = account_maps.get(&fork).unwrap().write().unwrap();
for parent_fork in parents.iter() { {
let parent_map = account_maps.get(&parent_fork).unwrap().read().unwrap(); let stores = self.storage.read().unwrap();
for (pubkey, account_info) in parent_map.iter() { for parent_fork in parents.iter() {
if account_map.get(pubkey).is_none() { let parent_map = account_maps.get(&parent_fork).unwrap().read().unwrap();
self.insert_account_entry(&pubkey, &account_info, &mut account_map); if account_map.len() > parent_map.len() {
for (pubkey, account_info) in parent_map.iter() {
if !account_map.contains_key(pubkey) {
stores[account_info.id].add_account();
account_map.insert(*pubkey, account_info.clone());
}
}
} else {
let mut maps = parent_map.clone();
for (_, account_info) in maps.iter() {
stores[account_info.id].add_account();
}
for (pubkey, account_info) in account_map.iter() {
if maps.insert(*pubkey, account_info.clone()).is_some() {
stores[account_info.id].remove_account();
}
}
*account_map = maps;
} }
} }
} }