Reduce banking_stage bench copy-paste code and fix programs bench (#4926)
This commit is contained in:
parent
b505a0df22
commit
94db9cd412
|
@ -18,13 +18,15 @@ use solana::poh_recorder::WorkingBankEntries;
|
||||||
use solana::service::Service;
|
use solana::service::Service;
|
||||||
use solana::test_tx::test_tx;
|
use solana::test_tx::test_tx;
|
||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_sdk::hash::hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use solana_sdk::signature::Keypair;
|
||||||
|
use solana_sdk::signature::KeypairUtil;
|
||||||
use solana_sdk::signature::Signature;
|
use solana_sdk::signature::Signature;
|
||||||
|
use solana_sdk::system_instruction;
|
||||||
use solana_sdk::system_transaction;
|
use solana_sdk::system_transaction;
|
||||||
use solana_sdk::timing::{
|
use solana_sdk::timing::{duration_as_us, timestamp};
|
||||||
duration_as_us, timestamp, DEFAULT_TICKS_PER_SLOT, MAX_RECENT_BLOCKHASHES,
|
use solana_sdk::transaction::Transaction;
|
||||||
};
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
|
@ -91,11 +93,49 @@ fn bench_consume_buffered(bencher: &mut Bencher) {
|
||||||
let _unused = Blocktree::destroy(&ledger_path);
|
let _unused = Blocktree::destroy(&ledger_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
fn make_accounts_txs(txes: usize, mint_keypair: &Keypair, hash: Hash) -> Vec<Transaction> {
|
||||||
fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) {
|
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<u8> = (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<Transaction> {
|
||||||
|
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();
|
solana_logger::setup();
|
||||||
let num_threads = BankingStage::num_threads() as usize;
|
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 CHUNKS: usize = 8;
|
||||||
const PACKETS_PER_BATCH: usize = 192;
|
const PACKETS_PER_BATCH: usize = 192;
|
||||||
let txes = PACKETS_PER_BATCH * num_threads * CHUNKS;
|
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 (verified_sender, verified_receiver) = unbounded();
|
||||||
let (vote_sender, vote_receiver) = unbounded();
|
let (vote_sender, vote_receiver) = unbounded();
|
||||||
let bank = Arc::new(Bank::new(&genesis_block));
|
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);
|
debug!("threads: {} txs: {}", num_threads, txes);
|
||||||
let transactions: Vec<_> = (0..txes)
|
|
||||||
.into_par_iter()
|
let transactions = match tx_type {
|
||||||
.map(|_| {
|
TransactionType::Accounts => make_accounts_txs(txes, &mint_keypair, genesis_block.hash()),
|
||||||
let mut new = dummy.clone();
|
TransactionType::Programs => make_programs_txs(txes, genesis_block.hash()),
|
||||||
let from: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
|
};
|
||||||
let to: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
|
|
||||||
let sig: Vec<u8> = (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();
|
|
||||||
// fund all the accounts
|
// fund all the accounts
|
||||||
transactions.iter().for_each(|tx| {
|
transactions.iter().for_each(|tx| {
|
||||||
let fund = system_transaction::transfer(
|
let fund = system_transaction::transfer(
|
||||||
|
@ -204,7 +236,7 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) {
|
||||||
check_txs(&signal_receiver2, txes / CHUNKS);
|
check_txs(&signal_receiver2, txes / CHUNKS);
|
||||||
|
|
||||||
// This signature clear may not actually clear the signatures
|
// 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.
|
// we should clear them by the time we come around again to re-use that chunk.
|
||||||
bank.clear_signatures();
|
bank.clear_signatures();
|
||||||
trace!(
|
trace!(
|
||||||
|
@ -224,124 +256,11 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[ignore]
|
fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) {
|
||||||
|
bench_banking(bencher, TransactionType::Accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
fn bench_banking_stage_multi_programs(bencher: &mut Bencher) {
|
fn bench_banking_stage_multi_programs(bencher: &mut Bencher) {
|
||||||
let progs = 4;
|
bench_banking(bencher, TransactionType::Programs);
|
||||||
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<u8> = (0..32).map(|_| thread_rng().gen()).collect();
|
|
||||||
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen()).collect();
|
|
||||||
let to: Vec<u8> = (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<u8> = (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();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue