Add accounts-filler-size command line option (#23896)

This commit is contained in:
Giorgio Gambino 2022-04-11 19:10:09 +01:00 committed by GitHub
parent eb478d72d1
commit 60b2155bd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 33 deletions

View File

@ -798,8 +798,7 @@ impl Validator {
let enable_gossip_push = config let enable_gossip_push = config
.accounts_db_config .accounts_db_config
.as_ref() .as_ref()
.and_then(|config| config.filler_account_count) .map(|config| config.filler_accounts_config.count == 0)
.map(|count| count == 0)
.unwrap_or(true); .unwrap_or(true);
let snapshot_packager_service = SnapshotPackagerService::new( let snapshot_packager_service = SnapshotPackagerService::new(

View File

@ -32,7 +32,7 @@ use {
}, },
solana_measure::measure::Measure, solana_measure::measure::Measure,
solana_runtime::{ solana_runtime::{
accounts_db::AccountsDbConfig, accounts_db::{AccountsDbConfig, FillerAccountsConfig},
accounts_index::{AccountsIndexConfig, ScanConfig}, accounts_index::{AccountsIndexConfig, ScanConfig},
bank::{Bank, RewardCalculationEvent}, bank::{Bank, RewardCalculationEvent},
bank_forks::BankForks, bank_forks::BankForks,
@ -928,7 +928,16 @@ fn main() {
.value_name("COUNT") .value_name("COUNT")
.validator(is_parsable::<usize>) .validator(is_parsable::<usize>)
.takes_value(true) .takes_value(true)
.default_value("0")
.help("How many accounts to add to stress the system. Accounts are ignored in operations related to correctness."); .help("How many accounts to add to stress the system. Accounts are ignored in operations related to correctness.");
let accounts_filler_size = Arg::with_name("accounts_filler_size")
.long("accounts-filler-size")
.value_name("BYTES")
.validator(is_parsable::<usize>)
.takes_value(true)
.default_value("0")
.requires("accounts_filler_count")
.help("Size per filler account in bytes.");
let account_paths_arg = Arg::with_name("account_paths") let account_paths_arg = Arg::with_name("account_paths")
.long("accounts") .long("accounts")
.value_name("PATHS") .value_name("PATHS")
@ -1283,6 +1292,7 @@ fn main() {
.arg(&disable_disk_index) .arg(&disable_disk_index)
.arg(&accountsdb_skip_shrink) .arg(&accountsdb_skip_shrink)
.arg(&accounts_filler_count) .arg(&accounts_filler_count)
.arg(&accounts_filler_size)
.arg(&verify_index_arg) .arg(&verify_index_arg)
.arg(&hard_forks_arg) .arg(&hard_forks_arg)
.arg(&no_accounts_db_caching_arg) .arg(&no_accounts_db_caching_arg)
@ -2066,13 +2076,15 @@ fn main() {
accounts_index_config.drives = Some(accounts_index_paths); accounts_index_config.drives = Some(accounts_index_paths);
} }
let filler_account_count = let filler_accounts_config = FillerAccountsConfig {
value_t!(arg_matches, "accounts_filler_count", usize).ok(); count: value_t_or_exit!(arg_matches, "accounts_filler_count", usize),
size: value_t_or_exit!(arg_matches, "accounts_filler_size", usize),
};
let accounts_db_config = Some(AccountsDbConfig { let accounts_db_config = Some(AccountsDbConfig {
index: Some(accounts_index_config), index: Some(accounts_index_config),
accounts_hash_cache_path: Some(ledger_path.clone()), accounts_hash_cache_path: Some(ledger_path.clone()),
filler_account_count, filler_accounts_config,
..AccountsDbConfig::default() ..AccountsDbConfig::default()
}); });

View File

@ -125,13 +125,12 @@ pub fn load_bank_forks(
accounts_update_notifier, accounts_update_notifier,
) )
} else { } else {
if process_options let maybe_filler_accounts = process_options
.accounts_db_config .accounts_db_config
.as_ref() .as_ref()
.and_then(|config| config.filler_account_count) .map(|config| config.filler_accounts_config.count > 0);
.unwrap_or_default()
> 0 if let Some(true) = maybe_filler_accounts {
{
panic!("filler accounts specified, but not loading from snapshot"); panic!("filler accounts specified, but not loading from snapshot");
} }

View File

@ -65,6 +65,7 @@ use {
genesis_config::{ClusterType, GenesisConfig}, genesis_config::{ClusterType, GenesisConfig},
hash::Hash, hash::Hash,
pubkey::Pubkey, pubkey::Pubkey,
rent::Rent,
timing::AtomicInterval, timing::AtomicInterval,
}, },
std::{ std::{
@ -128,14 +129,14 @@ const CACHE_VIRTUAL_STORED_SIZE: StoredSize = 0;
pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig { pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig {
index: Some(ACCOUNTS_INDEX_CONFIG_FOR_TESTING), index: Some(ACCOUNTS_INDEX_CONFIG_FOR_TESTING),
accounts_hash_cache_path: None, accounts_hash_cache_path: None,
filler_account_count: None, filler_accounts_config: FillerAccountsConfig::const_default(),
hash_calc_num_passes: None, hash_calc_num_passes: None,
write_cache_limit_bytes: None, write_cache_limit_bytes: None,
}; };
pub const ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS: AccountsDbConfig = AccountsDbConfig { pub const ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS: AccountsDbConfig = AccountsDbConfig {
index: Some(ACCOUNTS_INDEX_CONFIG_FOR_BENCHMARKS), index: Some(ACCOUNTS_INDEX_CONFIG_FOR_BENCHMARKS),
accounts_hash_cache_path: None, accounts_hash_cache_path: None,
filler_account_count: None, filler_accounts_config: FillerAccountsConfig::const_default(),
hash_calc_num_passes: None, hash_calc_num_passes: None,
write_cache_limit_bytes: None, write_cache_limit_bytes: None,
}; };
@ -148,11 +149,31 @@ pub struct AccountsAddRootTiming {
pub store_us: u64, pub store_us: u64,
} }
#[derive(Debug, Clone, Copy)]
pub struct FillerAccountsConfig {
/// Number of filler accounts
pub count: usize,
/// Data size per account, in bytes
pub size: usize,
}
impl FillerAccountsConfig {
pub const fn const_default() -> Self {
Self { count: 0, size: 0 }
}
}
impl Default for FillerAccountsConfig {
fn default() -> Self {
Self::const_default()
}
}
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct AccountsDbConfig { pub struct AccountsDbConfig {
pub index: Option<AccountsIndexConfig>, pub index: Option<AccountsIndexConfig>,
pub accounts_hash_cache_path: Option<PathBuf>, pub accounts_hash_cache_path: Option<PathBuf>,
pub filler_account_count: Option<usize>, pub filler_accounts_config: FillerAccountsConfig,
pub hash_calc_num_passes: Option<usize>, pub hash_calc_num_passes: Option<usize>,
pub write_cache_limit_bytes: Option<u64>, pub write_cache_limit_bytes: Option<u64>,
} }
@ -1090,7 +1111,7 @@ pub struct AccountsDb {
/// GeyserPlugin accounts update notifier /// GeyserPlugin accounts update notifier
accounts_update_notifier: Option<AccountsUpdateNotifier>, accounts_update_notifier: Option<AccountsUpdateNotifier>,
filler_account_count: usize, filler_accounts_config: FillerAccountsConfig,
pub filler_account_suffix: Option<Pubkey>, pub filler_account_suffix: Option<Pubkey>,
active_stats: ActiveStats, active_stats: ActiveStats,
@ -1633,7 +1654,7 @@ impl AccountsDb {
dirty_stores: DashMap::default(), dirty_stores: DashMap::default(),
zero_lamport_accounts_to_purge_after_full_snapshot: DashSet::default(), zero_lamport_accounts_to_purge_after_full_snapshot: DashSet::default(),
accounts_update_notifier: None, accounts_update_notifier: None,
filler_account_count: 0, filler_accounts_config: FillerAccountsConfig::default(),
filler_account_suffix: None, filler_account_suffix: None,
num_hash_scan_passes, num_hash_scan_passes,
} }
@ -1677,11 +1698,13 @@ impl AccountsDb {
let accounts_hash_cache_path = accounts_db_config let accounts_hash_cache_path = accounts_db_config
.as_ref() .as_ref()
.and_then(|x| x.accounts_hash_cache_path.clone()); .and_then(|x| x.accounts_hash_cache_path.clone());
let filler_account_count = accounts_db_config
let filler_accounts_config = accounts_db_config
.as_ref() .as_ref()
.and_then(|cfg| cfg.filler_account_count) .map(|config| config.filler_accounts_config)
.unwrap_or_default(); .unwrap_or_default();
let filler_account_suffix = if filler_account_count > 0 {
let filler_account_suffix = if filler_accounts_config.count > 0 {
Some(solana_sdk::pubkey::new_rand()) Some(solana_sdk::pubkey::new_rand())
} else { } else {
None None
@ -1694,7 +1717,7 @@ impl AccountsDb {
caching_enabled, caching_enabled,
shrink_ratio, shrink_ratio,
accounts_update_notifier, accounts_update_notifier,
filler_account_count, filler_accounts_config,
filler_account_suffix, filler_account_suffix,
write_cache_limit_bytes: accounts_db_config write_cache_limit_bytes: accounts_db_config
.as_ref() .as_ref()
@ -5741,7 +5764,7 @@ impl AccountsDb {
}; };
let hash = AccountsHash { let hash = AccountsHash {
filler_account_suffix: if self.filler_account_count > 0 { filler_account_suffix: if self.filler_accounts_config.count > 0 {
self.filler_account_suffix self.filler_account_suffix
} else { } else {
None None
@ -6857,15 +6880,18 @@ 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, epoch_schedule: &EpochSchedule) { pub fn maybe_add_filler_accounts(&self, epoch_schedule: &EpochSchedule, rent: &Rent) {
if self.filler_account_count == 0 { if self.filler_accounts_config.count == 0 {
return; return;
} }
let max_root_inclusive = self.accounts_index.max_root_inclusive(); let max_root_inclusive = self.accounts_index.max_root_inclusive();
let epoch = epoch_schedule.get_epoch(max_root_inclusive); let epoch = epoch_schedule.get_epoch(max_root_inclusive);
info!("adding {} filler accounts", self.filler_account_count); info!(
"adding {} filler accounts with size {}",
self.filler_accounts_config.count, self.filler_accounts_config.size,
);
// break this up to force the accounts out of memory after each pass // break this up to force the accounts out of memory after each pass
let passes = 100; let passes = 100;
let mut roots = self.storage.all_slots(); let mut roots = self.storage.all_slots();
@ -6879,8 +6905,9 @@ impl AccountsDb {
let string = "FiLLERACCoUNTooooooooooooooooooooooooooooooo"; let string = "FiLLERACCoUNTooooooooooooooooooooooooooooooo";
let hash = Hash::from_str(string).unwrap(); let hash = Hash::from_str(string).unwrap();
let owner = Pubkey::from_str(string).unwrap(); let owner = Pubkey::from_str(string).unwrap();
let lamports = 100_000_000; let space = self.filler_accounts_config.size;
let space = 0; let rent_exempt_reserve = rent.minimum_balance(space);
let lamports = rent_exempt_reserve;
let account = AccountSharedData::new(lamports, space, &owner); let account = AccountSharedData::new(lamports, space, &owner);
let added = AtomicUsize::default(); let added = AtomicUsize::default();
for pass in 0..=passes { for pass in 0..=passes {
@ -6907,8 +6934,8 @@ impl AccountsDb {
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);
let filler_entries = (idx + 1) * self.filler_account_count / root_count let filler_entries = (idx + 1) * self.filler_accounts_config.count / root_count
- idx * self.filler_account_count / root_count; - idx * self.filler_accounts_config.count / root_count;
let accounts = (0..filler_entries) let accounts = (0..filler_entries)
.map(|_| { .map(|_| {
let my_id = added.fetch_add(1, Ordering::Relaxed); let my_id = added.fetch_add(1, Ordering::Relaxed);

View File

@ -642,7 +642,7 @@ where
genesis_config, genesis_config,
); );
accounts_db.maybe_add_filler_accounts(&genesis_config.epoch_schedule); accounts_db.maybe_add_filler_accounts(&genesis_config.epoch_schedule, &genesis_config.rent);
handle.join().unwrap(); handle.join().unwrap();
measure_notify.stop(); measure_notify.stop();

View File

@ -42,8 +42,8 @@ use {
}, },
solana_runtime::{ solana_runtime::{
accounts_db::{ accounts_db::{
AccountShrinkThreshold, AccountsDbConfig, DEFAULT_ACCOUNTS_SHRINK_OPTIMIZE_TOTAL_SPACE, AccountShrinkThreshold, AccountsDbConfig, FillerAccountsConfig,
DEFAULT_ACCOUNTS_SHRINK_RATIO, DEFAULT_ACCOUNTS_SHRINK_OPTIMIZE_TOTAL_SPACE, DEFAULT_ACCOUNTS_SHRINK_RATIO,
}, },
accounts_index::{ accounts_index::{
AccountIndex, AccountSecondaryIndexes, AccountSecondaryIndexesIncludeExclude, AccountIndex, AccountSecondaryIndexes, AccountSecondaryIndexesIncludeExclude,
@ -1600,7 +1600,16 @@ pub fn main() {
.value_name("COUNT") .value_name("COUNT")
.validator(is_parsable::<usize>) .validator(is_parsable::<usize>)
.takes_value(true) .takes_value(true)
.default_value("0")
.help("How many accounts to add to stress the system. Accounts are ignored in operations related to correctness.")) .help("How many accounts to add to stress the system. Accounts are ignored in operations related to correctness."))
.arg(Arg::with_name("accounts_filler_size")
.long("accounts-filler-size")
.value_name("BYTES")
.validator(is_parsable::<usize>)
.takes_value(true)
.default_value("0")
.requires("accounts_filler_count")
.help("Size per filler account in bytes."))
.arg( .arg(
Arg::with_name("accounts_db_test_hash_calculation") Arg::with_name("accounts_db_test_hash_calculation")
.long("accounts-db-test-hash-calculation") .long("accounts-db-test-hash-calculation")
@ -2251,11 +2260,15 @@ pub fn main() {
.ok() .ok()
.map(|mb| mb * MB); .map(|mb| mb * MB);
let filler_account_count = value_t!(matches, "accounts_filler_count", usize).ok(); let filler_accounts_config = FillerAccountsConfig {
count: value_t_or_exit!(matches, "accounts_filler_count", usize),
size: value_t_or_exit!(matches, "accounts_filler_size", usize),
};
let mut accounts_db_config = AccountsDbConfig { let mut accounts_db_config = AccountsDbConfig {
index: Some(accounts_index_config), index: Some(accounts_index_config),
accounts_hash_cache_path: Some(ledger_path.clone()), accounts_hash_cache_path: Some(ledger_path.clone()),
filler_account_count, filler_accounts_config,
write_cache_limit_bytes: value_t!(matches, "accounts_db_cache_limit_mb", u64) write_cache_limit_bytes: value_t!(matches, "accounts_db_cache_limit_mb", u64)
.ok() .ok()
.map(|mb| mb * MB as u64), .map(|mb| mb * MB as u64),