FillerAccts: use variable cycle partitions (#20963)

This commit is contained in:
Jeff Washington (jwash) 2021-10-27 11:18:27 -05:00 committed by GitHub
parent bbd72a87c2
commit 9d330fc638
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 19 deletions

View File

@ -52,7 +52,8 @@ use solana_measure::measure::Measure;
use solana_rayon_threadlimit::get_thread_count; use solana_rayon_threadlimit::get_thread_count;
use solana_sdk::{ use solana_sdk::{
account::{AccountSharedData, ReadableAccount}, account::{AccountSharedData, ReadableAccount},
clock::{BankId, Epoch, Slot, SlotCount}, clock::{BankId, Epoch, Slot},
epoch_schedule::EpochSchedule,
genesis_config::ClusterType, genesis_config::ClusterType,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
pubkey::Pubkey, pubkey::Pubkey,
@ -6766,7 +6767,7 @@ impl AccountsDb {
/// The filler accounts are added to each slot in the snapshot after index generation. /// The filler accounts are added to each slot in the snapshot after index generation.
/// The accounts added in a slot are setup to have pubkeys such that rent will be collected from them before (or when?) their slot becomes an epoch old. /// The accounts added in a slot are setup to have pubkeys such that rent will be collected from them before (or when?) their slot becomes an epoch old.
/// Thus, the filler accounts are rewritten by rent and the old slot can be thrown away successfully. /// Thus, the filler accounts are rewritten by rent and the old slot can be thrown away successfully.
pub fn maybe_add_filler_accounts(&self, ticks_per_slot: SlotCount) { pub fn maybe_add_filler_accounts(&self, epoch_schedule: &EpochSchedule) {
if self.filler_account_count == 0 { if self.filler_account_count == 0 {
return; return;
} }
@ -6792,8 +6793,6 @@ impl AccountsDb {
.skip(pass * per_pass) .skip(pass * per_pass)
.take(per_pass) .take(per_pass)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let slot_count_in_two_day =
crate::bank::Bank::slot_count_in_two_day_helper(ticks_per_slot);
self.thread_pool.install(|| { self.thread_pool.install(|| {
roots_in_this_pass.into_par_iter().for_each(|slot| { roots_in_this_pass.into_par_iter().for_each(|slot| {
let storage_maps: Vec<Arc<AccountStorageEntry>> = self let storage_maps: Vec<Arc<AccountStorageEntry>> = self
@ -6804,13 +6803,10 @@ impl AccountsDb {
return; return;
} }
let partition = *crate::bank::Bank::get_partitions( let partition = crate::bank::Bank::variable_cycle_partition_from_previous_slot(
epoch_schedule,
*slot, *slot,
slot.saturating_sub(1), );
slot_count_in_two_day,
)
.last()
.unwrap();
let subrange = crate::bank::Bank::pubkey_range_from_partition(partition); let subrange = crate::bank::Bank::pubkey_range_from_partition(partition);
let idx = overall_index.fetch_add(1, Ordering::Relaxed); let idx = overall_index.fetch_add(1, Ordering::Relaxed);

View File

@ -4550,6 +4550,32 @@ impl Bank {
Self::get_partitions(self.slot(), self.parent_slot(), slot_count_in_two_day) Self::get_partitions(self.slot(), self.parent_slot(), slot_count_in_two_day)
} }
pub fn variable_cycle_partition_from_previous_slot(
epoch_schedule: &EpochSchedule,
slot: Slot,
) -> Partition {
// similar code to Bank::variable_cycle_partitions
let (current_epoch, current_slot_index) = epoch_schedule.get_epoch_and_slot_index(slot);
let (parent_epoch, mut parent_slot_index) =
epoch_schedule.get_epoch_and_slot_index(slot.saturating_sub(1));
let cycle_params = Self::rent_single_epoch_collection_cycle_params(
current_epoch,
epoch_schedule.get_slots_in_epoch(current_epoch),
);
if parent_epoch < current_epoch {
parent_slot_index = 0;
}
let generated_for_gapped_epochs = false;
Self::get_partition_from_slot_indexes(
cycle_params,
parent_slot_index,
current_slot_index,
generated_for_gapped_epochs,
)
}
fn variable_cycle_partitions(&self) -> Vec<Partition> { fn variable_cycle_partitions(&self) -> Vec<Partition> {
let (current_epoch, current_slot_index) = self.get_epoch_and_slot_index(self.slot()); let (current_epoch, current_slot_index) = self.get_epoch_and_slot_index(self.slot());
let (parent_epoch, mut parent_slot_index) = let (parent_epoch, mut parent_slot_index) =
@ -4600,6 +4626,20 @@ impl Bank {
generated_for_gapped_epochs: bool, generated_for_gapped_epochs: bool,
) -> Partition { ) -> Partition {
let cycle_params = self.determine_collection_cycle_params(epoch); let cycle_params = self.determine_collection_cycle_params(epoch);
Self::get_partition_from_slot_indexes(
cycle_params,
start_slot_index,
end_slot_index,
generated_for_gapped_epochs,
)
}
pub fn get_partition_from_slot_indexes(
cycle_params: RentCollectionCycleParams,
start_slot_index: SlotIndex,
end_slot_index: SlotIndex,
generated_for_gapped_epochs: bool,
) -> Partition {
let (_, _, in_multi_epoch_cycle, _, _, partition_count) = cycle_params; let (_, _, in_multi_epoch_cycle, _, _, partition_count) = cycle_params;
// use common codepath for both very likely and very unlikely for the sake of minimized // use common codepath for both very likely and very unlikely for the sake of minimized
@ -4669,18 +4709,26 @@ impl Bank {
self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true) self.do_partition_from_slot_indexes(start_slot_index, end_slot_index, epoch, true)
} }
pub fn rent_single_epoch_collection_cycle_params(
epoch: Epoch,
slot_count_per_epoch: SlotCount,
) -> RentCollectionCycleParams {
(
epoch,
slot_count_per_epoch,
false,
0,
1,
slot_count_per_epoch,
)
}
fn determine_collection_cycle_params(&self, epoch: Epoch) -> RentCollectionCycleParams { fn determine_collection_cycle_params(&self, epoch: Epoch) -> RentCollectionCycleParams {
let slot_count_per_epoch = self.get_slots_in_epoch(epoch); let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
if !self.use_multi_epoch_collection_cycle(epoch) { if !self.use_multi_epoch_collection_cycle(epoch) {
( // mnb should always go through this code path
epoch, Self::rent_single_epoch_collection_cycle_params(epoch, slot_count_per_epoch)
slot_count_per_epoch,
false,
0,
1,
slot_count_per_epoch,
)
} else { } else {
let epoch_count_in_cycle = self.slot_count_in_two_day() / slot_count_per_epoch; let epoch_count_in_cycle = self.slot_count_in_two_day() / slot_count_per_epoch;
let partition_count = slot_count_per_epoch * epoch_count_in_cycle; let partition_count = slot_count_per_epoch * epoch_count_in_cycle;
@ -7484,6 +7532,26 @@ pub(crate) mod tests {
assert_eq!(bank.collected_rent.load(Relaxed), rent_collected); assert_eq!(bank.collected_rent.load(Relaxed), rent_collected);
} }
fn test_rent_collection_partitions(bank: &Bank) -> Vec<Partition> {
let partitions = bank.rent_collection_partitions();
let slot = bank.slot();
if slot.saturating_sub(1) == bank.parent_slot() {
let partition = Bank::variable_cycle_partition_from_previous_slot(
bank.epoch_schedule(),
bank.slot(),
);
assert_eq!(
partitions.last().unwrap(),
&partition,
"slot: {}, slots per epoch: {}, partitions: {:?}",
bank.slot(),
bank.epoch_schedule().slots_per_epoch,
partitions
);
}
partitions
}
#[test] #[test]
fn test_rent_eager_across_epoch_without_gap() { fn test_rent_eager_across_epoch_without_gap() {
let (genesis_config, _mint_keypair) = create_genesis_config(1); let (genesis_config, _mint_keypair) = create_genesis_config(1);
@ -7501,6 +7569,25 @@ pub(crate) mod tests {
assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 64)]); assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 64)]);
} }
#[test]
fn test_rent_eager_across_epoch_without_gap_mnb() {
solana_logger::setup();
let (mut genesis_config, _mint_keypair) = create_genesis_config(1);
genesis_config.cluster_type = ClusterType::MainnetBeta;
let mut bank = Arc::new(Bank::new_for_tests(&genesis_config));
assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 0, 32)]);
bank = Arc::new(new_from_parent(&bank));
assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 1, 32)]);
for _ in 2..32 {
bank = Arc::new(new_from_parent(&bank));
}
assert_eq!(test_rent_collection_partitions(&bank), vec![(30, 31, 32)]);
bank = Arc::new(new_from_parent(&bank));
assert_eq!(test_rent_collection_partitions(&bank), vec![(0, 0, 64)]);
}
#[test] #[test]
fn test_rent_eager_across_epoch_with_full_gap() { fn test_rent_eager_across_epoch_with_full_gap() {
let (mut genesis_config, _mint_keypair) = create_genesis_config(1); let (mut genesis_config, _mint_keypair) = create_genesis_config(1);

View File

@ -548,7 +548,7 @@ where
.unwrap(); .unwrap();
accounts_db.generate_index(limit_load_slot_count_from_snapshot, verify_index); accounts_db.generate_index(limit_load_slot_count_from_snapshot, verify_index);
accounts_db.maybe_add_filler_accounts(genesis_config.ticks_per_slot()); accounts_db.maybe_add_filler_accounts(&genesis_config.epoch_schedule);
handle.join().unwrap(); handle.join().unwrap();
measure_notify.stop(); measure_notify.stop();