Fix issues with bench-tps (#4005)

This commit is contained in:
Sagar Dhawan 2019-04-27 08:39:29 -07:00 committed by GitHub
parent 4a5837a286
commit 18e398131d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 16 deletions

View File

@ -5,6 +5,7 @@ use solana::gen_keys::GenKeys;
use solana_drone::drone::request_airdrop_transaction; use solana_drone::drone::request_airdrop_transaction;
use solana_metrics::influxdb; use solana_metrics::influxdb;
use solana_sdk::client::Client; use solana_sdk::client::Client;
use solana_sdk::hash::Hash;
use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::signature::{Keypair, KeypairUtil};
use solana_sdk::system_instruction; use solana_sdk::system_instruction;
use solana_sdk::system_transaction; use solana_sdk::system_transaction;
@ -136,21 +137,32 @@ pub fn do_bench_tps<T>(
let start = Instant::now(); let start = Instant::now();
let mut reclaim_lamports_back_to_source_account = false; let mut reclaim_lamports_back_to_source_account = false;
let mut i = keypair0_balance; let mut i = keypair0_balance;
let mut blockhash = Hash::default();
let mut blockhash_time = Instant::now();
while start.elapsed() < duration { 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 // ping-pong between source and destination accounts for each loop iteration
// this seems to be faster than trying to determine the balance of individual // this seems to be faster than trying to determine the balance of individual
// accounts // accounts
let len = tx_count as usize; 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( generate_txs(
&shared_txs, &shared_txs,
&blockhash,
&keypairs[..len], &keypairs[..len],
&keypairs[len..], &keypairs[len..],
threads, threads,
reclaim_lamports_back_to_source_account, reclaim_lamports_back_to_source_account,
&client,
); );
// In sustained mode overlap the transfers with generation // In sustained mode overlap the transfers with generation
// this has higher average performance but lower peak performance // this has higher average performance but lower peak performance
@ -265,15 +277,14 @@ fn sample_tx_count<T: Client>(
} }
} }
fn generate_txs<T: Client>( fn generate_txs(
shared_txs: &SharedTransactions, shared_txs: &SharedTransactions,
blockhash: &Hash,
source: &[Keypair], source: &[Keypair],
dest: &[Keypair], dest: &[Keypair],
threads: usize, threads: usize,
reclaim: bool, reclaim: bool,
client: &Arc<T>,
) { ) {
let blockhash = client.get_recent_blockhash().unwrap();
let tx_count = source.len(); let tx_count = source.len();
println!("Signing transactions... {} (reclaim={})", tx_count, reclaim); println!("Signing transactions... {} (reclaim={})", tx_count, reclaim);
let signing_start = Instant::now(); let signing_start = Instant::now();
@ -287,7 +298,7 @@ fn generate_txs<T: Client>(
.par_iter() .par_iter()
.map(|(id, keypair)| { .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(), timestamp(),
) )
}) })
@ -630,9 +641,10 @@ pub fn generate_keypairs(id: &Keypair, tx_count: usize) -> Vec<Keypair> {
let mut total_keys = 0; let mut total_keys = 0;
let mut target = tx_count * 2; let mut target = tx_count * 2;
while target > 0 { while target > 1 {
total_keys += target; 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) rnd.gen_n_keypairs(total_keys as u64)
} }

View File

@ -60,14 +60,14 @@ fn main() {
.collect(); .collect();
println!("Creating {} keypairs...", tx_count * 2); println!("Creating {} keypairs...", tx_count * 2);
let keypairs = generate_keypairs(&id, tx_count); let mut keypairs = generate_keypairs(&id, tx_count);
println!("Get lamports..."); println!("Get lamports...");
// Sample the first keypair, see if it has lamports, if so then resume. // 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 // This logic is to prevent lamport loss on repeated solana-bench-tps executions
let keypair0_balance = clients[0] let keypair0_balance = clients[0]
.get_balance(&keypairs.last().unwrap().pubkey()) .get_balance(&keypairs[tx_count * 2 - 1].pubkey())
.unwrap_or(0); .unwrap_or(0);
if NUM_LAMPORTS_PER_ACCOUNT > keypair0_balance { if NUM_LAMPORTS_PER_ACCOUNT > keypair0_balance {
@ -77,6 +77,8 @@ fn main() {
println!("adding more lamports {}", extra); println!("adding more lamports {}", extra);
fund_keys(&clients[0], &id, &keypairs, 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 { let config = Config {
id, id,

View File

@ -115,10 +115,6 @@ impl ThinClient {
)) ))
} }
pub fn get_new_blockhash(&self, blockhash: &Hash) -> io::Result<Hash> {
self.rpc_client.get_new_blockhash(blockhash)
}
pub fn poll_balance_with_timeout( pub fn poll_balance_with_timeout(
&self, &self,
pubkey: &Pubkey, pubkey: &Pubkey,
@ -238,6 +234,11 @@ impl SyncClient for ThinClient {
fn poll_for_signature(&self, signature: &Signature) -> TransportResult<()> { fn poll_for_signature(&self, signature: &Signature) -> TransportResult<()> {
Ok(self.rpc_client.poll_for_signature(signature)?) Ok(self.rpc_client.poll_for_signature(signature)?)
} }
fn get_new_blockhash(&self, blockhash: &Hash) -> TransportResult<Hash> {
let new_blockhash = self.rpc_client.get_new_blockhash(blockhash)?;
Ok(new_blockhash)
}
} }
impl AsyncClient for ThinClient { impl AsyncClient for ThinClient {

View File

@ -166,6 +166,18 @@ impl SyncClient for BankClient {
} }
Ok(()) Ok(())
} }
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<Hash> {
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 { impl BankClient {

View File

@ -60,6 +60,8 @@ pub trait SyncClient {
/// Poll to confirm a transaction. /// Poll to confirm a transaction.
fn poll_for_signature(&self, signature: &Signature) -> Result<()>; fn poll_for_signature(&self, signature: &Signature) -> Result<()>;
fn get_new_blockhash(&self, blockhash: &Hash) -> Result<Hash>;
} }
pub trait AsyncClient { pub trait AsyncClient {