Add option to reclaim accounts-cluster-bench accounts/lamports (#21656)
* Add option to reclaim accounts-cluster-bench accounts/lamports * lint
This commit is contained in:
parent
f6801a4af4
commit
205fd95722
|
@ -4276,6 +4276,7 @@ dependencies = [
|
||||||
"solana-runtime",
|
"solana-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"solana-streamer",
|
"solana-streamer",
|
||||||
|
"solana-test-validator",
|
||||||
"solana-transaction-status",
|
"solana-transaction-status",
|
||||||
"solana-version",
|
"solana-version",
|
||||||
"spl-token",
|
"spl-token",
|
||||||
|
|
|
@ -25,6 +25,7 @@ solana-net-utils = { path = "../net-utils", version = "=1.10.0" }
|
||||||
solana-runtime = { path = "../runtime", version = "=1.10.0" }
|
solana-runtime = { path = "../runtime", version = "=1.10.0" }
|
||||||
solana-sdk = { path = "../sdk", version = "=1.10.0" }
|
solana-sdk = { path = "../sdk", version = "=1.10.0" }
|
||||||
solana-streamer = { path = "../streamer", version = "=1.10.0" }
|
solana-streamer = { path = "../streamer", version = "=1.10.0" }
|
||||||
|
solana-test-validator = { path = "../test-validator", version = "=1.10.0" }
|
||||||
solana-transaction-status = { path = "../transaction-status", version = "=1.10.0" }
|
solana-transaction-status = { path = "../transaction-status", version = "=1.10.0" }
|
||||||
solana-version = { path = "../version", version = "=1.10.0" }
|
solana-version = { path = "../version", version = "=1.10.0" }
|
||||||
spl-token = { version = "=3.2.0", features = ["no-entrypoint"] }
|
spl-token = { version = "=3.2.0", features = ["no-entrypoint"] }
|
||||||
|
|
|
@ -23,6 +23,7 @@ use {
|
||||||
solana_streamer::socket::SocketAddrSpace,
|
solana_streamer::socket::SocketAddrSpace,
|
||||||
solana_transaction_status::parse_token::spl_token_instruction,
|
solana_transaction_status::parse_token::spl_token_instruction,
|
||||||
std::{
|
std::{
|
||||||
|
cmp::min,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
process::exit,
|
process::exit,
|
||||||
sync::{
|
sync::{
|
||||||
|
@ -156,24 +157,30 @@ fn make_create_message(
|
||||||
fn make_close_message(
|
fn make_close_message(
|
||||||
keypair: &Keypair,
|
keypair: &Keypair,
|
||||||
base_keypair: &Keypair,
|
base_keypair: &Keypair,
|
||||||
max_closed_seed: Arc<AtomicU64>,
|
max_created: Arc<AtomicU64>,
|
||||||
|
max_closed: Arc<AtomicU64>,
|
||||||
num_instructions: usize,
|
num_instructions: usize,
|
||||||
balance: u64,
|
balance: u64,
|
||||||
spl_token: bool,
|
spl_token: bool,
|
||||||
) -> Message {
|
) -> Message {
|
||||||
let instructions: Vec<_> = (0..num_instructions)
|
let instructions: Vec<_> = (0..num_instructions)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|_| {
|
.filter_map(|_| {
|
||||||
let program_id = if spl_token {
|
let program_id = if spl_token {
|
||||||
inline_spl_token::id()
|
inline_spl_token::id()
|
||||||
} else {
|
} else {
|
||||||
system_program::id()
|
system_program::id()
|
||||||
};
|
};
|
||||||
let seed = max_closed_seed.fetch_add(1, Ordering::Relaxed).to_string();
|
let max_created_seed = max_created.load(Ordering::Relaxed);
|
||||||
|
let max_closed_seed = max_closed.load(Ordering::Relaxed);
|
||||||
|
if max_closed_seed >= max_created_seed {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let seed = max_closed.fetch_add(1, Ordering::Relaxed).to_string();
|
||||||
let address =
|
let address =
|
||||||
Pubkey::create_with_seed(&base_keypair.pubkey(), &seed, &program_id).unwrap();
|
Pubkey::create_with_seed(&base_keypair.pubkey(), &seed, &program_id).unwrap();
|
||||||
if spl_token {
|
if spl_token {
|
||||||
spl_token_instruction(
|
Some(spl_token_instruction(
|
||||||
spl_token::instruction::close_account(
|
spl_token::instruction::close_account(
|
||||||
&spl_token::id(),
|
&spl_token::id(),
|
||||||
&spl_token_pubkey(&address),
|
&spl_token_pubkey(&address),
|
||||||
|
@ -182,16 +189,16 @@ fn make_close_message(
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
))
|
||||||
} else {
|
} else {
|
||||||
system_instruction::transfer_with_seed(
|
Some(system_instruction::transfer_with_seed(
|
||||||
&address,
|
&address,
|
||||||
&base_keypair.pubkey(),
|
&base_keypair.pubkey(),
|
||||||
seed,
|
seed,
|
||||||
&program_id,
|
&program_id,
|
||||||
&keypair.pubkey(),
|
&keypair.pubkey(),
|
||||||
balance,
|
balance,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -211,6 +218,7 @@ fn run_accounts_bench(
|
||||||
maybe_lamports: Option<u64>,
|
maybe_lamports: Option<u64>,
|
||||||
num_instructions: usize,
|
num_instructions: usize,
|
||||||
mint: Option<Pubkey>,
|
mint: Option<Pubkey>,
|
||||||
|
reclaim_accounts: bool,
|
||||||
) {
|
) {
|
||||||
assert!(num_instructions > 0);
|
assert!(num_instructions > 0);
|
||||||
let client =
|
let client =
|
||||||
|
@ -350,6 +358,7 @@ fn run_accounts_bench(
|
||||||
let message = make_close_message(
|
let message = make_close_message(
|
||||||
payer_keypairs[0],
|
payer_keypairs[0],
|
||||||
&base_keypair,
|
&base_keypair,
|
||||||
|
seed_tracker.max_created.clone(),
|
||||||
seed_tracker.max_closed.clone(),
|
seed_tracker.max_closed.clone(),
|
||||||
1,
|
1,
|
||||||
min_balance,
|
min_balance,
|
||||||
|
@ -372,7 +381,7 @@ fn run_accounts_bench(
|
||||||
}
|
}
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
if last_log.elapsed().as_millis() > 3000 {
|
if last_log.elapsed().as_millis() > 3000 || count >= iterations {
|
||||||
info!(
|
info!(
|
||||||
"total_accounts_created: {} total_accounts_closed: {} tx_sent_count: {} loop_count: {} balance(s): {:?}",
|
"total_accounts_created: {} total_accounts_closed: {} tx_sent_count: {} loop_count: {} balance(s): {:?}",
|
||||||
total_accounts_created, total_accounts_closed, tx_sent_count, count, balances
|
total_accounts_created, total_accounts_closed, tx_sent_count, count, balances
|
||||||
|
@ -387,6 +396,83 @@ fn run_accounts_bench(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
executor.close();
|
executor.close();
|
||||||
|
|
||||||
|
if reclaim_accounts {
|
||||||
|
let executor = TransactionExecutor::new(entrypoint_addr);
|
||||||
|
loop {
|
||||||
|
let max_closed_seed = seed_tracker.max_closed.load(Ordering::Relaxed);
|
||||||
|
let max_created_seed = seed_tracker.max_created.load(Ordering::Relaxed);
|
||||||
|
|
||||||
|
if latest_blockhash.elapsed().as_millis() > 10_000 {
|
||||||
|
blockhash = client.get_latest_blockhash().expect("blockhash");
|
||||||
|
latest_blockhash = Instant::now();
|
||||||
|
}
|
||||||
|
message.recent_blockhash = blockhash;
|
||||||
|
let fee = client
|
||||||
|
.get_fee_for_message(&message)
|
||||||
|
.expect("get_fee_for_message");
|
||||||
|
|
||||||
|
let sigs_len = executor.num_outstanding();
|
||||||
|
if sigs_len < batch_size && max_closed_seed < max_created_seed {
|
||||||
|
let num_to_close = min(
|
||||||
|
batch_size - sigs_len,
|
||||||
|
(max_created_seed - max_closed_seed) as usize,
|
||||||
|
);
|
||||||
|
if num_to_close >= payer_keypairs.len() {
|
||||||
|
info!("closing {} accounts", num_to_close);
|
||||||
|
let chunk_size = num_to_close / payer_keypairs.len();
|
||||||
|
info!("{:?} chunk_size", chunk_size);
|
||||||
|
if chunk_size > 0 {
|
||||||
|
for (i, keypair) in payer_keypairs.iter().enumerate() {
|
||||||
|
let txs: Vec<_> = (0..chunk_size)
|
||||||
|
.into_par_iter()
|
||||||
|
.filter_map(|_| {
|
||||||
|
let message = make_close_message(
|
||||||
|
keypair,
|
||||||
|
&base_keypair,
|
||||||
|
seed_tracker.max_created.clone(),
|
||||||
|
seed_tracker.max_closed.clone(),
|
||||||
|
num_instructions,
|
||||||
|
min_balance,
|
||||||
|
mint.is_some(),
|
||||||
|
);
|
||||||
|
if message.instructions.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let signers: Vec<&Keypair> = vec![keypair, &base_keypair];
|
||||||
|
Some(Transaction::new(&signers, message, blockhash))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
balances[i] = balances[i].saturating_sub(fee * txs.len() as u64);
|
||||||
|
info!("close txs: {}", txs.len());
|
||||||
|
let new_ids = executor.push_transactions(txs);
|
||||||
|
info!("close ids: {}", new_ids.len());
|
||||||
|
tx_sent_count += new_ids.len();
|
||||||
|
total_accounts_closed += (num_instructions * new_ids.len()) as u64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let _ = executor.drain_cleared();
|
||||||
|
}
|
||||||
|
count += 1;
|
||||||
|
if last_log.elapsed().as_millis() > 3000 || max_closed_seed >= max_created_seed {
|
||||||
|
info!(
|
||||||
|
"total_accounts_closed: {} tx_sent_count: {} loop_count: {} balance(s): {:?}",
|
||||||
|
total_accounts_closed, tx_sent_count, count, balances
|
||||||
|
);
|
||||||
|
last_log = Instant::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
if max_closed_seed >= max_created_seed {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if executor.num_outstanding() >= batch_size {
|
||||||
|
sleep(Duration::from_millis(500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executor.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -462,7 +548,7 @@ fn main() {
|
||||||
.long("iterations")
|
.long("iterations")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("NUM")
|
.value_name("NUM")
|
||||||
.help("Number of iterations to make"),
|
.help("Number of iterations to make. 0 = unlimited iterations."),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("check_gossip")
|
Arg::with_name("check_gossip")
|
||||||
|
@ -475,6 +561,12 @@ fn main() {
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Mint address to initialize account"),
|
.help("Mint address to initialize account"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("reclaim_accounts")
|
||||||
|
.long("reclaim-accounts")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Reclaim accounts after session ends; incompatible with --iterations 0"),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let skip_gossip = !matches.is_present("check_gossip");
|
let skip_gossip = !matches.is_present("check_gossip");
|
||||||
|
@ -556,6 +648,7 @@ fn main() {
|
||||||
lamports,
|
lamports,
|
||||||
num_instructions,
|
num_instructions,
|
||||||
mint,
|
mint,
|
||||||
|
matches.is_present("reclaim_accounts"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,12 +657,18 @@ pub mod test {
|
||||||
use {
|
use {
|
||||||
super::*,
|
super::*,
|
||||||
solana_core::validator::ValidatorConfig,
|
solana_core::validator::ValidatorConfig,
|
||||||
|
solana_faucet::faucet::run_local_faucet,
|
||||||
solana_local_cluster::{
|
solana_local_cluster::{
|
||||||
local_cluster::{ClusterConfig, LocalCluster},
|
local_cluster::{ClusterConfig, LocalCluster},
|
||||||
validator_configs::make_identical_validator_configs,
|
validator_configs::make_identical_validator_configs,
|
||||||
},
|
},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
solana_sdk::poh_config::PohConfig,
|
solana_sdk::{native_token::sol_to_lamports, poh_config::PohConfig},
|
||||||
|
solana_test_validator::TestValidator,
|
||||||
|
spl_token::{
|
||||||
|
solana_program::program_pack::Pack,
|
||||||
|
state::{Account, Mint},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -605,6 +704,108 @@ pub mod test {
|
||||||
maybe_lamports,
|
maybe_lamports,
|
||||||
num_instructions,
|
num_instructions,
|
||||||
None,
|
None,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
start.stop();
|
||||||
|
info!("{}", start);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_then_reclaim_spl_token_accounts() {
|
||||||
|
solana_logger::setup();
|
||||||
|
let mint_keypair = Keypair::new();
|
||||||
|
let mint_pubkey = mint_keypair.pubkey();
|
||||||
|
let faucet_addr = run_local_faucet(mint_keypair, None);
|
||||||
|
let test_validator = TestValidator::with_custom_fees(
|
||||||
|
mint_pubkey,
|
||||||
|
1,
|
||||||
|
Some(faucet_addr),
|
||||||
|
SocketAddrSpace::Unspecified,
|
||||||
|
);
|
||||||
|
let rpc_client =
|
||||||
|
RpcClient::new_with_commitment(test_validator.rpc_url(), CommitmentConfig::processed());
|
||||||
|
|
||||||
|
// Created funder
|
||||||
|
let funder = Keypair::new();
|
||||||
|
let latest_blockhash = rpc_client.get_latest_blockhash().unwrap();
|
||||||
|
let signature = rpc_client
|
||||||
|
.request_airdrop_with_blockhash(
|
||||||
|
&funder.pubkey(),
|
||||||
|
sol_to_lamports(1.0),
|
||||||
|
&latest_blockhash,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
rpc_client
|
||||||
|
.confirm_transaction_with_spinner(
|
||||||
|
&signature,
|
||||||
|
&latest_blockhash,
|
||||||
|
CommitmentConfig::confirmed(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Create Mint
|
||||||
|
let spl_mint_keypair = Keypair::new();
|
||||||
|
let spl_mint_len = Mint::get_packed_len();
|
||||||
|
let spl_mint_rent = rpc_client
|
||||||
|
.get_minimum_balance_for_rent_exemption(spl_mint_len)
|
||||||
|
.unwrap();
|
||||||
|
let transaction = Transaction::new_signed_with_payer(
|
||||||
|
&[
|
||||||
|
system_instruction::create_account(
|
||||||
|
&funder.pubkey(),
|
||||||
|
&spl_mint_keypair.pubkey(),
|
||||||
|
spl_mint_rent,
|
||||||
|
spl_mint_len as u64,
|
||||||
|
&inline_spl_token::id(),
|
||||||
|
),
|
||||||
|
spl_token_instruction(
|
||||||
|
spl_token::instruction::initialize_mint(
|
||||||
|
&spl_token::id(),
|
||||||
|
&spl_token_pubkey(&spl_mint_keypair.pubkey()),
|
||||||
|
&spl_token_pubkey(&spl_mint_keypair.pubkey()),
|
||||||
|
None,
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Some(&funder.pubkey()),
|
||||||
|
&[&funder, &spl_mint_keypair],
|
||||||
|
latest_blockhash,
|
||||||
|
);
|
||||||
|
let _sig = rpc_client
|
||||||
|
.send_and_confirm_transaction(&transaction)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let account_len = Account::get_packed_len();
|
||||||
|
let minimum_balance = rpc_client
|
||||||
|
.get_minimum_balance_for_rent_exemption(account_len)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let iterations = 5;
|
||||||
|
let batch_size = 100;
|
||||||
|
let close_nth_batch = 0;
|
||||||
|
let num_instructions = 4;
|
||||||
|
let mut start = Measure::start("total accounts run");
|
||||||
|
let keypair0 = Keypair::new();
|
||||||
|
let keypair1 = Keypair::new();
|
||||||
|
let keypair2 = Keypair::new();
|
||||||
|
run_accounts_bench(
|
||||||
|
test_validator
|
||||||
|
.rpc_url()
|
||||||
|
.replace("http://", "")
|
||||||
|
.parse()
|
||||||
|
.unwrap(),
|
||||||
|
faucet_addr,
|
||||||
|
&[&keypair0, &keypair1, &keypair2],
|
||||||
|
iterations,
|
||||||
|
Some(account_len as u64),
|
||||||
|
batch_size,
|
||||||
|
close_nth_batch,
|
||||||
|
Some(minimum_balance),
|
||||||
|
num_instructions,
|
||||||
|
Some(spl_mint_keypair.pubkey()),
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
start.stop();
|
start.stop();
|
||||||
info!("{}", start);
|
info!("{}", start);
|
||||||
|
|
Loading…
Reference in New Issue