get rid of acquisition of read lock while unrefing accounts in scan (#27388)
This commit is contained in:
parent
574097f640
commit
1154bc8636
|
@ -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),
|
||||
)
|
||||
})
|
||||
});
|
||||
|
|
|
@ -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, ())
|
||||
|
|
Loading…
Reference in New Issue