Reduce account index lookups during clean (#16689)

* reduce account index lookups in clean

* rename

* rename enum

* hold locks during removal from zero pubkey list

* merge with zero lamport fix

* tests
This commit is contained in:
Jeff Washington (jwash)
2021-04-23 09:33:14 -05:00
committed by GitHub
parent 03194145c0
commit 91be2903da
2 changed files with 105 additions and 50 deletions

View File

@@ -85,6 +85,12 @@ impl<T> AccountMapEntryInner<T> {
}
}
pub enum AccountIndexGetResult<'a, T: 'static, U> {
Found(ReadAccountMapEntry<T>, usize),
NotFoundOnFork,
Missing(std::sync::RwLockReadGuard<'a, AccountMap<U, AccountMapEntry<T>>>),
}
#[self_referencing]
pub struct ReadAccountMapEntry<T: 'static> {
owned_entry: AccountMapEntry<T>,
@@ -694,7 +700,9 @@ impl<T: 'static + Clone + IsCached + ZeroLamport> AccountsIndex<T> {
for pubkey in index.get(index_key) {
// Maybe these reads from the AccountsIndex can be batched every time it
// grabs the read lock as well...
if let Some((list_r, index)) = self.get(&pubkey, Some(ancestors), max_root) {
if let AccountIndexGetResult::Found(list_r, index) =
self.get(&pubkey, Some(ancestors), max_root)
{
func(
&pubkey,
(&list_r.slot_list()[index].1, list_r.slot_list()[index].0),
@@ -936,13 +944,25 @@ impl<T: 'static + Clone + IsCached + ZeroLamport> AccountsIndex<T> {
pubkey: &Pubkey,
ancestors: Option<&Ancestors>,
max_root: Option<Slot>,
) -> Option<(ReadAccountMapEntry<T>, usize)> {
self.get_account_read_entry(pubkey)
.and_then(|locked_entry| {
let found_index =
self.latest_slot(ancestors, &locked_entry.slot_list(), max_root)?;
Some((locked_entry, found_index))
})
) -> AccountIndexGetResult<'_, T, Pubkey> {
let read_lock = self.account_maps.read().unwrap();
let account = read_lock
.get(pubkey)
.cloned()
.map(ReadAccountMapEntry::from_account_map_entry);
match account {
Some(locked_entry) => {
drop(read_lock);
let slot_list = locked_entry.slot_list();
let found_index = self.latest_slot(ancestors, slot_list, max_root);
match found_index {
Some(found_index) => AccountIndexGetResult::Found(locked_entry, found_index),
None => AccountIndexGetResult::NotFoundOnFork,
}
}
None => AccountIndexGetResult::Missing(read_lock),
}
}
// Get the maximum root <= `max_allowed_root` from the given `slice`
@@ -1320,6 +1340,32 @@ pub mod tests {
account_indexes
}
impl<'a, T: 'static, U> AccountIndexGetResult<'a, T, U> {
pub fn unwrap(self) -> (ReadAccountMapEntry<T>, usize) {
match self {
AccountIndexGetResult::Found(lock, size) => (lock, size),
_ => {
panic!("trying to unwrap AccountIndexGetResult with non-Success result");
}
}
}
pub fn is_none(&self) -> bool {
!self.is_some()
}
pub fn is_some(&self) -> bool {
matches!(self, AccountIndexGetResult::Found(_lock, _size))
}
pub fn map<V, F: FnOnce((ReadAccountMapEntry<T>, usize)) -> V>(self, f: F) -> Option<V> {
match self {
AccountIndexGetResult::Found(lock, size) => Some(f((lock, size))),
_ => None,
}
}
}
fn create_dashmap_secondary_index_state() -> (usize, usize, HashSet<AccountIndex>) {
{
// Check that we're actually testing the correct variant