Skip to content

Commit

Permalink
AcctIdx: hold ranges in memory uses multiple threads (solana-labs#22031)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffwashington authored Dec 21, 2021
1 parent 5b464a3 commit bdae299
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 26 deletions.
36 changes: 22 additions & 14 deletions runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,13 +870,17 @@ impl Accounts {
)
}

pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
where
R: RangeBounds<Pubkey> + std::fmt::Debug,
pub fn hold_range_in_memory<R>(
&self,
range: &R,
start_holding: bool,
thread_pool: &rayon::ThreadPool,
) where
R: RangeBounds<Pubkey> + std::fmt::Debug + Sync,
{
self.accounts_db
.accounts_index
.hold_range_in_memory(range, start_holding)
.hold_range_in_memory(range, start_holding, thread_pool)
}

pub fn load_to_collect_rent_eagerly<R: RangeBounds<Pubkey> + std::fmt::Debug>(
Expand Down Expand Up @@ -1331,12 +1335,12 @@ mod tests {
fn test_hold_range_in_memory() {
let accts = Accounts::default_for_tests();
let range = Pubkey::new(&[0; 32])..=Pubkey::new(&[0xff; 32]);
accts.hold_range_in_memory(&range, true);
accts.hold_range_in_memory(&range, false);
accts.hold_range_in_memory(&range, true);
accts.hold_range_in_memory(&range, true);
accts.hold_range_in_memory(&range, false);
accts.hold_range_in_memory(&range, false);
accts.hold_range_in_memory(&range, true, &test_thread_pool());
accts.hold_range_in_memory(&range, false, &test_thread_pool());
accts.hold_range_in_memory(&range, true, &test_thread_pool());
accts.hold_range_in_memory(&range, true, &test_thread_pool());
accts.hold_range_in_memory(&range, false, &test_thread_pool());
accts.hold_range_in_memory(&range, false, &test_thread_pool());
}

#[test]
Expand All @@ -1353,15 +1357,15 @@ mod tests {
let range2_inclusive = range2.start..=range2.end;
assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.start));
assert_eq!(0, idx.bin_calculator.bin_from_pubkey(&range2.end));
accts.hold_range_in_memory(&range, true);
accts.hold_range_in_memory(&range, true, &test_thread_pool());
idx.account_maps.iter().enumerate().for_each(|(_bin, map)| {
let map = map.read().unwrap();
assert_eq!(
map.cache_ranges_held.read().unwrap().to_vec(),
vec![range.clone()]
);
});
accts.hold_range_in_memory(&range2, true);
accts.hold_range_in_memory(&range2, true, &test_thread_pool());
idx.account_maps.iter().enumerate().for_each(|(bin, map)| {
let map = map.read().unwrap();
let expected = if bin == 0 {
Expand All @@ -1376,8 +1380,12 @@ mod tests {
bin
);
});
accts.hold_range_in_memory(&range, false);
accts.hold_range_in_memory(&range2, false);
accts.hold_range_in_memory(&range, false, &test_thread_pool());
accts.hold_range_in_memory(&range2, false, &test_thread_pool());
}

fn test_thread_pool() -> rayon::ThreadPool {
crate::accounts_db::make_min_priority_thread_pool()
}

#[test]
Expand Down
25 changes: 15 additions & 10 deletions runtime/src/accounts_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use {
log::*,
ouroboros::self_referencing,
rand::{thread_rng, Rng},
rayon::{
iter::{IntoParallelIterator, ParallelIterator},
ThreadPool,
},
solana_measure::measure::Measure,
solana_sdk::{
clock::{BankId, Slot},
Expand Down Expand Up @@ -742,21 +746,22 @@ impl<'a, T: IndexValue> AccountsIndexIterator<'a, T> {
}
}

pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool, thread_pool: &ThreadPool)
where
R: RangeBounds<Pubkey> + Debug,
R: RangeBounds<Pubkey> + Debug + Sync,
{
// forward this hold request ONLY to the bins which contain keys in the specified range
let (start_bin, bin_range) = self.bin_start_and_range();
self.account_maps
.iter()
.skip(start_bin)
.take(bin_range)
.for_each(|map| {
// the idea is this range shouldn't be more than a few buckets, but the process of loading from disk buckets is very slow
// so, parallelize the bucket loads
thread_pool.install(|| {
(0..bin_range).into_par_iter().for_each(|idx| {
let map = &self.account_maps[idx + start_bin];
map.read()
.unwrap()
.hold_range_in_memory(range, start_holding);
});
});
}
}

Expand Down Expand Up @@ -1460,12 +1465,12 @@ impl<T: IndexValue> AccountsIndex<T> {
rv.map(|index| slice.len() - 1 - index)
}

pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool)
pub fn hold_range_in_memory<R>(&self, range: &R, start_holding: bool, thread_pool: &ThreadPool)
where
R: RangeBounds<Pubkey> + Debug,
R: RangeBounds<Pubkey> + Debug + Sync,
{
let iter = self.iter(Some(range), true);
iter.hold_range_in_memory(range, start_holding);
iter.hold_range_in_memory(range, start_holding, thread_pool);
}

pub fn set_startup(&self, value: bool) {
Expand Down
9 changes: 7 additions & 2 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4179,7 +4179,10 @@ impl Bank {
fn collect_rent_in_partition(&self, partition: Partition) -> usize {
let subrange = Self::pubkey_range_from_partition(partition);

self.rc.accounts.hold_range_in_memory(&subrange, true);
let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
self.rc
.accounts
.hold_range_in_memory(&subrange, true, thread_pool);

let accounts = self
.rc
Expand Down Expand Up @@ -4213,7 +4216,9 @@ impl Bank {
.unwrap()
.extend(rent_debits.into_unordered_rewards_iter());

self.rc.accounts.hold_range_in_memory(&subrange, false);
self.rc
.accounts
.hold_range_in_memory(&subrange, false, thread_pool);
account_count
}

Expand Down

0 comments on commit bdae299

Please sign in to comment.