diff --git a/bench-tps/src/bench.rs b/bench-tps/src/bench.rs index 7b8aae9f9e..c83640171d 100644 --- a/bench-tps/src/bench.rs +++ b/bench-tps/src/bench.rs @@ -5,6 +5,7 @@ use solana::gen_keys::GenKeys; use solana_drone::drone::request_airdrop_transaction; use solana_metrics::influxdb; use solana_sdk::client::Client; +use solana_sdk::hash::Hash; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction; use solana_sdk::system_transaction; @@ -136,21 +137,32 @@ pub fn do_bench_tps( let start = Instant::now(); let mut reclaim_lamports_back_to_source_account = false; let mut i = keypair0_balance; + let mut blockhash = Hash::default(); + let mut blockhash_time = Instant::now(); while start.elapsed() < duration { - let balance = client.get_balance(&id.pubkey()).unwrap_or(0); - metrics_submit_lamport_balance(balance); - // ping-pong between source and destination accounts for each loop iteration // this seems to be faster than trying to determine the balance of individual // accounts let len = tx_count as usize; + if let Ok(new_blockhash) = client.get_new_blockhash(&blockhash) { + blockhash = new_blockhash; + } else { + if blockhash_time.elapsed().as_secs() > 30 { + panic!("Blockhash is not updating"); + } + sleep(Duration::from_millis(100)); + continue; + } + blockhash_time = Instant::now(); + let balance = client.get_balance(&id.pubkey()).unwrap_or(0); + metrics_submit_lamport_balance(balance); generate_txs( &shared_txs, + &blockhash, &keypairs[..len], &keypairs[len..], threads, reclaim_lamports_back_to_source_account, - &client, ); // In sustained mode overlap the transfers with generation // this has higher average performance but lower peak performance @@ -265,15 +277,14 @@ fn sample_tx_count( } } -fn generate_txs( +fn generate_txs( shared_txs: &SharedTransactions, + blockhash: &Hash, source: &[Keypair], dest: &[Keypair], threads: usize, reclaim: bool, - client: &Arc, ) { - let blockhash = client.get_recent_blockhash().unwrap(); let tx_count = source.len(); println!("Signing transactions... {} (reclaim={})", tx_count, reclaim); let signing_start = Instant::now(); @@ -287,7 +298,7 @@ fn generate_txs( .par_iter() .map(|(id, keypair)| { ( - system_transaction::create_user_account(id, &keypair.pubkey(), 1, blockhash, 0), + system_transaction::create_user_account(id, &keypair.pubkey(), 1, *blockhash, 0), timestamp(), ) }) @@ -630,9 +641,10 @@ pub fn generate_keypairs(id: &Keypair, tx_count: usize) -> Vec { let mut total_keys = 0; let mut target = tx_count * 2; - while target > 0 { + while target > 1 { total_keys += target; - target /= MAX_SPENDS_PER_TX; + // Use the upper bound for this division otherwise it may not generate enough keys + target = (target + MAX_SPENDS_PER_TX - 1) / MAX_SPENDS_PER_TX; } rnd.gen_n_keypairs(total_keys as u64) } diff --git a/bench-tps/src/main.rs b/bench-tps/src/main.rs index f3b254a8e3..4951460bf0 100644 --- a/bench-tps/src/main.rs +++ b/bench-tps/src/main.rs @@ -60,14 +60,14 @@ fn main() { .collect(); println!("Creating {} keypairs...", tx_count * 2); - let keypairs = generate_keypairs(&id, tx_count); + let mut keypairs = generate_keypairs(&id, tx_count); println!("Get lamports..."); // Sample the first keypair, see if it has lamports, if so then resume. // This logic is to prevent lamport loss on repeated solana-bench-tps executions let keypair0_balance = clients[0] - .get_balance(&keypairs.last().unwrap().pubkey()) + .get_balance(&keypairs[tx_count * 2 - 1].pubkey()) .unwrap_or(0); if NUM_LAMPORTS_PER_ACCOUNT > keypair0_balance { @@ -77,6 +77,8 @@ fn main() { println!("adding more lamports {}", extra); fund_keys(&clients[0], &id, &keypairs, extra); } + // 'generate_keypairs' generates extra keys to be able to have size-aligned funding batches for fund_keys. + keypairs.truncate(2 * tx_count); let config = Config { id, diff --git a/client/src/thin_client.rs b/client/src/thin_client.rs index b94fa583af..79632f4293 100644 --- a/client/src/thin_client.rs +++ b/client/src/thin_client.rs @@ -115,10 +115,6 @@ impl ThinClient { )) } - pub fn get_new_blockhash(&self, blockhash: &Hash) -> io::Result { - self.rpc_client.get_new_blockhash(blockhash) - } - pub fn poll_balance_with_timeout( &self, pubkey: &Pubkey, @@ -238,6 +234,11 @@ impl SyncClient for ThinClient { fn poll_for_signature(&self, signature: &Signature) -> TransportResult<()> { Ok(self.rpc_client.poll_for_signature(signature)?) } + + fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult { + let new_blockhash = self.rpc_client.get_new_blockhash(blockhash)?; + Ok(new_blockhash) + } } impl AsyncClient for ThinClient { diff --git a/runtime/src/bank_client.rs b/runtime/src/bank_client.rs index 7a5f5e97e4..c75dd77088 100644 --- a/runtime/src/bank_client.rs +++ b/runtime/src/bank_client.rs @@ -166,6 +166,18 @@ impl SyncClient for BankClient { } Ok(()) } + + fn get_new_blockhash(&self, blockhash: &Hash) -> Result { + let last_blockhash = self.bank.last_blockhash(); + if last_blockhash != *blockhash { + Ok(last_blockhash) + } else { + Err(TransportError::IoError(io::Error::new( + io::ErrorKind::Other, + "Unable to get new blockhash", + ))) + } + } } impl BankClient { diff --git a/sdk/src/client.rs b/sdk/src/client.rs index 0dd03cf177..42b03aee03 100644 --- a/sdk/src/client.rs +++ b/sdk/src/client.rs @@ -60,6 +60,8 @@ pub trait SyncClient { /// Poll to confirm a transaction. fn poll_for_signature(&self, signature: &Signature) -> Result<()>; + + fn get_new_blockhash(&self, blockhash: &Hash) -> Result; } pub trait AsyncClient {