Accounts index opt (#4621)

* Add accounts_index bench

* Don't take the accounts index lock unless needed

* Accounts_index remove insert return vec and add capacity stats

* Use hashbrown hashmap for accounts_index
This commit is contained in:
sakridge
2019-06-10 18:15:39 -07:00
committed by GitHub
parent 73491e3ca1
commit 966b6999d1
4 changed files with 131 additions and 49 deletions

View File

@ -474,14 +474,14 @@ impl AccountsDB {
fork_id: Fork,
infos: Vec<AccountInfo>,
accounts: &[(&Pubkey, &Account)],
) -> Vec<(Fork, AccountInfo)> {
) -> (Vec<(Fork, AccountInfo)>, u64) {
let mut reclaims = Vec::with_capacity(infos.len() * 2);
let mut index = self.accounts_index.write().unwrap();
let mut reclaims = vec![];
for (i, info) in infos.into_iter().enumerate() {
let key = &accounts[i].0;
reclaims.extend(index.insert(fork_id, key, info).into_iter())
index.insert(fork_id, key, info, &mut reclaims);
}
reclaims
(reclaims, index.last_root)
}
fn remove_dead_accounts(&self, reclaims: Vec<(Fork, AccountInfo)>) -> HashSet<Fork> {
@ -516,24 +516,30 @@ impl AccountsDB {
dead_forks
}
fn cleanup_dead_forks(&self, dead_forks: &mut HashSet<Fork>) {
let mut index = self.accounts_index.write().unwrap();
fn cleanup_dead_forks(&self, dead_forks: &mut HashSet<Fork>, last_root: u64) {
// a fork is not totally dead until it is older than the root
dead_forks.retain(|fork| *fork < index.last_root);
for fork in dead_forks.iter() {
index.cleanup_dead_fork(*fork);
dead_forks.retain(|fork| *fork < last_root);
if !dead_forks.is_empty() {
let mut index = self.accounts_index.write().unwrap();
for fork in dead_forks.iter() {
index.cleanup_dead_fork(*fork);
}
}
}
/// Store the account update.
pub fn store(&self, fork_id: Fork, accounts: &[(&Pubkey, &Account)]) {
let infos = self.store_accounts(fork_id, accounts);
let reclaims = self.update_index(fork_id, infos, accounts);
let (reclaims, last_root) = self.update_index(fork_id, infos, accounts);
trace!("reclaim: {}", reclaims.len());
let mut dead_forks = self.remove_dead_accounts(reclaims);
trace!("dead_forks: {}", dead_forks.len());
self.cleanup_dead_forks(&mut dead_forks);
self.cleanup_dead_forks(&mut dead_forks, last_root);
trace!("purge_forks: {}", dead_forks.len());
for fork in dead_forks {
self.purge_fork(fork);
}
@ -1182,7 +1188,14 @@ mod tests {
.clone();
//fork 0 is behind root, but it is not root, therefore it is purged
accounts.add_root(1);
assert!(accounts.accounts_index.read().unwrap().is_purged(0));
{
let accounts_index = accounts.accounts_index.read().unwrap();
assert!(AccountsIndex::<AccountInfo>::is_purged(
&accounts_index.roots,
accounts_index.last_root,
0
));
}
//fork is still there, since gc is lazy
assert!(accounts.storage.read().unwrap().0[&0]