diff --git a/core/benches/banking_stage.rs b/core/benches/banking_stage.rs index fa78c6a775..ed28d54801 100644 --- a/core/benches/banking_stage.rs +++ b/core/benches/banking_stage.rs @@ -18,13 +18,15 @@ use solana::poh_recorder::WorkingBankEntries; use solana::service::Service; use solana::test_tx::test_tx; use solana_runtime::bank::Bank; -use solana_sdk::hash::hash; +use solana_sdk::hash::Hash; use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::Keypair; +use solana_sdk::signature::KeypairUtil; use solana_sdk::signature::Signature; +use solana_sdk::system_instruction; use solana_sdk::system_transaction; -use solana_sdk::timing::{ - duration_as_us, timestamp, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES, -}; +use solana_sdk::timing::{duration_as_us, timestamp}; +use solana_sdk::transaction::Transaction; use std::iter; use std::sync::atomic::Ordering; use std::sync::mpsc::Receiver; @@ -91,11 +93,49 @@ fn bench_consume_buffered(bencher: &mut Bencher) { let _unused = Blocktree::destroy(&ledger_path); } -#[bench] -fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) { +fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec { + let to_pubkey = Pubkey::new_rand(); + let dummy = system_transaction::transfer(mint_keypair, &to_pubkey, 1, hash); + (0..txes) + .into_par_iter() + .map(|_| { + let mut new = dummy.clone(); + let sig: Vec = (0..64).map(|_| thread_rng().gen()).collect(); + new.message.account_keys[0] = Pubkey::new_rand(); + new.message.account_keys[1] = Pubkey::new_rand(); + new.signatures = vec![Signature::new(&sig[0..64])]; + new + }) + .collect() +} + +fn make_programs_txs(txes: usize, hash: Hash) -> Vec { + let progs = 4; + (0..txes) + .into_iter() + .map(|_| { + let mut instructions = vec![]; + let from_key = Keypair::new(); + for _ in 1..progs { + let to_key = Pubkey::new_rand(); + instructions.push(system_instruction::transfer(&from_key.pubkey(), &to_key, 1)); + } + let mut new = Transaction::new_unsigned_instructions(instructions); + new.sign(&[&from_key], hash); + new + }) + .collect() +} + +enum TransactionType { + Accounts, + Programs, +} + +fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) { solana_logger::setup(); let num_threads = BankingStage::num_threads() as usize; - // a multiple of packet chunk 2X duplicates to avoid races + // a multiple of packet chunk duplicates to avoid races const CHUNKS: usize = 8; const PACKETS_PER_BATCH: usize = 192; let txes = PACKETS_PER_BATCH * num_threads * CHUNKS; @@ -113,22 +153,14 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) { let (verified_sender, verified_receiver) = unbounded(); let (vote_sender, vote_receiver) = unbounded(); let bank = Arc::new(Bank::new(&genesis_block)); - let to_pubkey = Pubkey::new_rand(); - let dummy = system_transaction::transfer(&mint_keypair, &to_pubkey, 1, genesis_block.hash()); + debug!("threads: {} txs: {}", num_threads, txes); - let transactions: Vec<_> = (0..txes) - .into_par_iter() - .map(|_| { - let mut new = dummy.clone(); - let from: Vec = (0..64).map(|_| thread_rng().gen()).collect(); - let to: Vec = (0..64).map(|_| thread_rng().gen()).collect(); - let sig: Vec = (0..64).map(|_| thread_rng().gen()).collect(); - new.message.account_keys[0] = Pubkey::new(&from[0..32]); - new.message.account_keys[1] = Pubkey::new(&to[0..32]); - new.signatures = vec![Signature::new(&sig[0..64])]; - new - }) - .collect(); + + let transactions = match tx_type { + TransactionType::Accounts => make_accounts_txs(txes, &mint_keypair, genesis_block.hash()), + TransactionType::Programs => make_programs_txs(txes, genesis_block.hash()), + }; + // fund all the accounts transactions.iter().for_each(|tx| { let fund = system_transaction::transfer( @@ -204,7 +236,7 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) { check_txs(&signal_receiver2, txes / CHUNKS); // This signature clear may not actually clear the signatures - // in this chunk, but since we rotate between 32 chunks then + // in this chunk, but since we rotate between CHUNKS then // we should clear them by the time we come around again to re-use that chunk. bank.clear_signatures(); trace!( @@ -224,124 +256,11 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) { } #[bench] -#[ignore] -fn bench_banking_stage_multi_programs(bencher: &mut Bencher) { - let progs = 4; - let num_threads = BankingStage::num_threads() as usize; - // a multiple of packet chunk 2X duplicates to avoid races - let txes = 96 * 100 * num_threads * 2; - let mint_total = 1_000_000_000_000; - let GenesisBlockInfo { - genesis_block, - mint_keypair, - .. - } = create_genesis_block(mint_total); - - let (verified_sender, verified_receiver) = unbounded(); - let (vote_sender, vote_receiver) = unbounded(); - let bank = Arc::new(Bank::new(&genesis_block)); - let to_pubkey = Pubkey::new_rand(); - let dummy = system_transaction::transfer(&mint_keypair, &to_pubkey, 1, genesis_block.hash()); - let transactions: Vec<_> = (0..txes) - .into_par_iter() - .map(|_| { - let mut new = dummy.clone(); - let from: Vec = (0..32).map(|_| thread_rng().gen()).collect(); - let sig: Vec = (0..64).map(|_| thread_rng().gen()).collect(); - let to: Vec = (0..32).map(|_| thread_rng().gen()).collect(); - new.message.account_keys[0] = Pubkey::new(&from[0..32]); - new.message.account_keys[1] = Pubkey::new(&to[0..32]); - let prog = new.message.instructions[0].clone(); - for i in 1..progs { - //generate programs that spend to random keys - let to: Vec = (0..32).map(|_| thread_rng().gen()).collect(); - let to_key = Pubkey::new(&to[0..32]); - new.message.account_keys.push(to_key); - assert_eq!(new.message.account_keys.len(), i + 2); - new.message.instructions.push(prog.clone()); - assert_eq!(new.message.instructions.len(), i + 1); - new.message.instructions[i].accounts[1] = 1 + i as u8; - assert_eq!(new.key(i, 1), Some(&to_key)); - assert_eq!( - new.message.account_keys[new.message.instructions[i].accounts[1] as usize], - to_key - ); - } - assert_eq!(new.message.instructions.len(), progs); - new.signatures = vec![Signature::new(&sig[0..64])]; - new - }) - .collect(); - transactions.iter().for_each(|tx| { - let fund = system_transaction::transfer( - &mint_keypair, - &tx.message.account_keys[0], - mint_total / txes as u64, - genesis_block.hash(), - ); - bank.process_transaction(&fund).unwrap(); - }); - //sanity check, make sure all the transactions can execute sequentially - transactions.iter().for_each(|tx| { - let res = bank.process_transaction(&tx); - assert!(res.is_ok(), "sanity test transactions"); - }); - bank.clear_signatures(); - //sanity check, make sure all the transactions can execute in parallel - let res = bank.process_transactions(&transactions); - for r in res { - assert!(r.is_ok(), "sanity parallel execution"); - } - bank.clear_signatures(); - let verified: Vec<_> = to_packets_chunked(&transactions.clone(), 96) - .into_iter() - .map(|x| { - let len = x.packets.len(); - (x, iter::repeat(1).take(len).collect()) - }) - .collect(); - - let ledger_path = get_tmp_ledger_path!(); - { - let blocktree = Arc::new( - Blocktree::open(&ledger_path).expect("Expected to be able to open database ledger"), - ); - let (exit, poh_recorder, poh_service, signal_receiver) = - create_test_recorder(&bank, &blocktree); - let cluster_info = ClusterInfo::new_with_invalid_keypair(Node::new_localhost().info); - let cluster_info = Arc::new(RwLock::new(cluster_info)); - let _banking_stage = BankingStage::new( - &cluster_info, - &poh_recorder, - verified_receiver, - vote_receiver, - ); - poh_recorder.lock().unwrap().set_bank(&bank); - - let mut id = genesis_block.hash(); - for _ in 0..(MAX_RECENT_BLOCKHASHES * DEFAULT_TICKS_PER_SLOT as usize) { - id = hash(&id.as_ref()); - bank.register_tick(&id); - } - - let half_len = verified.len() / 2; - let mut start = 0; - let signal_receiver = Arc::new(signal_receiver); - let signal_receiver2 = signal_receiver.clone(); - bencher.iter(move || { - // make sure the transactions are still valid - bank.register_tick(&genesis_block.hash()); - for v in verified[start..start + half_len].chunks(verified.len() / num_threads) { - verified_sender.send(v.to_vec()).unwrap(); - } - check_txs(&signal_receiver2, txes / 2); - bank.clear_signatures(); - start += half_len; - start %= verified.len(); - }); - drop(vote_sender); - exit.store(true, Ordering::Relaxed); - poh_service.join().unwrap(); - } - Blocktree::destroy(&ledger_path).unwrap(); +fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) { + bench_banking(bencher, TransactionType::Accounts); +} + +#[bench] +fn bench_banking_stage_multi_programs(bencher: &mut Bencher) { + bench_banking(bencher, TransactionType::Programs); }