randomize tx ordering (#4978)

Summary of Changes:
This change adds functionality to randomize tx execution for every entry. It does this by implementing OrderedIterator that iterates tx slice as per the order specified. The order is generated randomly for every entry.
This commit is contained in:
Parth
2019-08-28 21:08:32 +05:30
committed by GitHub
parent 1609765740
commit 7dfb735db9
12 changed files with 451 additions and 99 deletions

View File

@@ -10,14 +10,18 @@ use rand::{thread_rng, Rng};
use rayon::prelude::*;
use solana_core::banking_stage::{create_test_recorder, BankingStage};
use solana_core::blocktree::{get_tmp_ledger_path, Blocktree};
use solana_core::blocktree_processor::process_entries;
use solana_core::cluster_info::ClusterInfo;
use solana_core::cluster_info::Node;
use solana_core::entry::next_hash;
use solana_core::entry::Entry;
use solana_core::genesis_utils::{create_genesis_block, GenesisBlockInfo};
use solana_core::packet::to_packets_chunked;
use solana_core::poh_recorder::WorkingBankEntries;
use solana_core::service::Service;
use solana_core::test_tx::test_tx;
use solana_runtime::bank::Bank;
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::hash::Hash;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Keypair;
@@ -264,3 +268,83 @@ fn bench_banking_stage_multi_accounts(bencher: &mut Bencher) {
fn bench_banking_stage_multi_programs(bencher: &mut Bencher) {
bench_banking(bencher, TransactionType::Programs);
}
fn simulate_process_entries(
randomize_txs: bool,
mint_keypair: &Keypair,
mut tx_vector: Vec<Transaction>,
genesis_block: &GenesisBlock,
keypairs: &Vec<Keypair>,
initial_lamports: u64,
num_accounts: usize,
) {
let bank = Bank::new(genesis_block);
for i in 0..(num_accounts / 2) {
bank.transfer(initial_lamports, mint_keypair, &keypairs[i * 2].pubkey())
.unwrap();
}
for i in (0..num_accounts).step_by(2) {
tx_vector.push(system_transaction::transfer(
&keypairs[i],
&keypairs[i + 1].pubkey(),
initial_lamports,
bank.last_blockhash(),
));
}
// Transfer lamports to each other
let entry = Entry {
num_hashes: 1,
hash: next_hash(&bank.last_blockhash(), 1, &tx_vector),
transactions: tx_vector,
};
process_entries(&bank, &vec![entry], randomize_txs).unwrap();
}
fn bench_process_entries(randomize_txs: bool, bencher: &mut Bencher) {
// entropy multiplier should be big enough to provide sufficient entropy
// but small enough to not take too much time while executing the test.
let entropy_multiplier: usize = 25;
let initial_lamports = 100;
// number of accounts need to be in multiple of 4 for correct
// execution of the test.
let num_accounts = entropy_multiplier * 4;
let GenesisBlockInfo {
genesis_block,
mint_keypair,
..
} = create_genesis_block((num_accounts + 1) as u64 * initial_lamports);
let mut keypairs: Vec<Keypair> = vec![];
let tx_vector: Vec<Transaction> = Vec::with_capacity(num_accounts / 2);
for _ in 0..num_accounts {
let keypair = Keypair::new();
keypairs.push(keypair);
}
bencher.iter(|| {
simulate_process_entries(
randomize_txs,
&mint_keypair,
tx_vector.clone(),
&genesis_block,
&keypairs,
initial_lamports,
num_accounts,
);
});
}
#[bench]
fn bench_process_entries_without_order_shuffeling(bencher: &mut Bencher) {
bench_process_entries(false, bencher);
}
#[bench]
fn bench_process_entries_with_order_shuffeling(bencher: &mut Bencher) {
bench_process_entries(true, bencher);
}