FillerAccts: use variable cycle partitions (#20963)
This commit is contained in:
parent
bbd72a87c2
commit
9d330fc638
|
@ -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);
|
||||||
|
|
|
@ -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,10 +4709,10 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_collection_cycle_params(&self, epoch: Epoch) -> RentCollectionCycleParams {
|
pub fn rent_single_epoch_collection_cycle_params(
|
||||||
let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
|
epoch: Epoch,
|
||||||
|
slot_count_per_epoch: SlotCount,
|
||||||
if !self.use_multi_epoch_collection_cycle(epoch) {
|
) -> RentCollectionCycleParams {
|
||||||
(
|
(
|
||||||
epoch,
|
epoch,
|
||||||
slot_count_per_epoch,
|
slot_count_per_epoch,
|
||||||
|
@ -4681,6 +4721,14 @@ impl Bank {
|
||||||
1,
|
1,
|
||||||
slot_count_per_epoch,
|
slot_count_per_epoch,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn determine_collection_cycle_params(&self, epoch: Epoch) -> RentCollectionCycleParams {
|
||||||
|
let slot_count_per_epoch = self.get_slots_in_epoch(epoch);
|
||||||
|
|
||||||
|
if !self.use_multi_epoch_collection_cycle(epoch) {
|
||||||
|
// mnb should always go through this code path
|
||||||
|
Self::rent_single_epoch_collection_cycle_params(epoch, 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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue