parallel rent collection avoids overlapping ranges (#25991)

This commit is contained in:
Jeff Washington (jwash) 2022-06-15 16:04:38 -05:00 committed by GitHub
parent 99cf1e280e
commit 631ea93259
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 54 additions and 9 deletions

View File

@ -5156,12 +5156,47 @@ impl Bank {
let count = partitions.len();
let rent_metrics = RentMetrics::default();
// partitions will usually be 1, but could be more if we skip slots
let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
thread_pool.install(|| {
partitions.into_par_iter().for_each(|partition| {
let mut parallel = count > 1;
if parallel {
let ranges = partitions
.iter()
.map(|partition| Self::pubkey_range_from_partition(*partition))
.collect::<Vec<_>>();
// test every range to make sure ranges are not overlapping
// some tests collect rent from overlapping ranges
// example: [(0, 31, 32), (0, 0, 128), (0, 27, 128)]
// read-modify-write of an account for rent collection cannot be done in parallel
'outer: for i in 0..ranges.len() {
for j in 0..ranges.len() {
if i == j {
continue;
}
let i = &ranges[i];
let j = &ranges[j];
// make sure i doesn't contain j
if i.contains(j.start()) || i.contains(j.end()) {
parallel = false;
break 'outer;
}
}
}
if parallel {
let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
thread_pool.install(|| {
ranges.into_par_iter().for_each(|range| {
self.collect_rent_in_range(range, just_rewrites, &rent_metrics)
});
});
}
}
if !parallel {
// collect serially
partitions.into_iter().for_each(|partition| {
self.collect_rent_in_partition(partition, just_rewrites, &rent_metrics)
});
});
}
measure.stop();
datapoint_info!(
"collect_rent_eagerly",
@ -5292,11 +5327,7 @@ impl Bank {
}
}
/// load accounts with pubkeys in 'partition'
/// collect rent
/// store accounts, whether rent was collected or not
/// update bank's rewrites set for all rewrites that were skipped
/// if 'just_rewrites', function will only update bank's rewrites set and not actually store any accounts
/// convert 'partition' to a pubkey range and 'collect_rent_in_range'
fn collect_rent_in_partition(
&self,
partition: Partition,
@ -5304,7 +5335,21 @@ impl Bank {
metrics: &RentMetrics,
) {
let subrange_full = Self::pubkey_range_from_partition(partition);
self.collect_rent_in_range(subrange_full, just_rewrites, metrics)
}
/// load accounts with pubkeys in 'subrange_full'
/// collect rent and update 'account.rent_epoch' as necessary
/// store accounts, whether rent was collected or not (depending on whether we skipping rewrites is enabled)
/// update bank's rewrites set for all rewrites that were skipped
/// if 'just_rewrites', function will only update bank's rewrites set and not actually store any accounts.
/// This flag is used when restoring from a snapshot to calculate and verify the initial bank's delta hash.
fn collect_rent_in_range(
&self,
subrange_full: RangeInclusive<Pubkey>,
just_rewrites: bool,
metrics: &RentMetrics,
) {
let mut hold_range = Measure::start("hold_range");
let thread_pool = &self.rc.accounts.accounts_db.thread_pool;
thread_pool.install(|| {