get rid of acquisition of read lock while unrefing accounts in scan (#27388)

This commit is contained in:
Jeff Washington (jwash) 2022-08-30 14:04:02 -05:00 committed by GitHub
parent 574097f640
commit 1154bc8636
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 10 deletions

View File

@ -2631,8 +2631,9 @@ impl AccountsDb {
let mut not_found_on_fork = 0;
let mut missing = 0;
let mut useful = 0;
self.accounts_index
.scan(pubkeys.iter(), |pubkey, slots_refs| {
self.accounts_index.scan(
pubkeys.iter(),
|pubkey, slots_refs| {
let mut useless = true;
if let Some((slot_list, ref_count)) = slots_refs {
let index_in_slot_list = self.accounts_index.latest_slot(
@ -2696,7 +2697,9 @@ impl AccountsDb {
} else {
AccountsIndexScanResult::KeepInMemory
}
});
},
None,
);
found_not_zero_accum.fetch_add(found_not_zero, Ordering::Relaxed);
not_found_on_fork_accum.fetch_add(not_found_on_fork, Ordering::Relaxed);
missing_accum.fetch_add(missing, Ordering::Relaxed);
@ -3191,6 +3194,7 @@ impl AccountsDb {
index += 1;
result
},
None,
);
assert_eq!(index, std::cmp::min(accounts.len(), count));
self.shrink_stats
@ -7598,7 +7602,8 @@ impl AccountsDb {
.skip(skip)
.take(BATCH_SIZE)
.map(|(_slot, pubkey)| pubkey),
|_pubkey, _slots_refs| AccountsIndexScanResult::Unref,
|_pubkey, _slots_refs| /* unused */AccountsIndexScanResult::Unref,
Some(AccountsIndexScanResult::Unref),
)
})
});

View File

@ -651,6 +651,7 @@ impl ScanSlotTracker {
}
}
#[derive(Copy, Clone)]
pub enum AccountsIndexScanResult {
/// if the entry is not in the in-memory index, do not add it, make no modifications to it
None,
@ -1342,15 +1343,22 @@ impl<T: IndexValue> AccountsIndex<T> {
}
/// For each pubkey, find the slot list in the accounts index
/// call `callback`
pub(crate) fn scan<'a, F, I>(&'a self, pubkeys: I, mut callback: F)
where
/// apply 'avoid_callback_result' if specified.
/// otherwise, call `callback`
pub(crate) fn scan<'a, F, I>(
&'a self,
pubkeys: I,
mut callback: F,
avoid_callback_result: Option<AccountsIndexScanResult>,
) where
// params:
// pubkey looked up
// slots_refs is Option<(slot_list, ref_count)>
// None if 'pubkey' is not in accounts index.
// slot_list: comes from accounts index for 'pubkey'
// ref_count: refcount of entry in index
// if 'avoid_callback_result' is Some(_), then callback is NOT called
// and _ is returned as if callback were called.
F: FnMut(&'a Pubkey, Option<(&SlotList<T>, RefCount)>) -> AccountsIndexScanResult,
I: IntoIterator<Item = &'a Pubkey>,
{
@ -1367,8 +1375,12 @@ impl<T: IndexValue> AccountsIndex<T> {
let mut cache = false;
match entry {
Some(locked_entry) => {
let slot_list = &locked_entry.slot_list.read().unwrap();
let result = callback(pubkey, Some((slot_list, locked_entry.ref_count())));
let result = if let Some(result) = avoid_callback_result.as_ref() {
*result
} else {
let slot_list = &locked_entry.slot_list.read().unwrap();
callback(pubkey, Some((slot_list, locked_entry.ref_count())))
};
cache = match result {
AccountsIndexScanResult::Unref => {
locked_entry.add_un_ref(false);
@ -1379,7 +1391,7 @@ impl<T: IndexValue> AccountsIndex<T> {
};
}
None => {
callback(pubkey, None);
avoid_callback_result.unwrap_or_else(|| callback(pubkey, None));
}
}
(cache, ())