update banking-bench to simulate mint event (#28489)
* update banking-bench to simulate mint event by specifying certain percentage of conflicting transactions with higher priority fee * set proper compute-unit for transfer transactions
This commit is contained in:
parent
d98eb97842
commit
365e32a484
|
@ -16,14 +16,14 @@ use {
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
solana_perf::packet::{to_packet_batches, PacketBatch},
|
solana_perf::packet::{to_packet_batches, PacketBatch},
|
||||||
solana_poh::poh_recorder::{create_test_recorder, PohRecorder, WorkingBankEntry},
|
solana_poh::poh_recorder::{create_test_recorder, PohRecorder, WorkingBankEntry},
|
||||||
solana_runtime::{
|
solana_runtime::{bank::Bank, bank_forks::BankForks, cost_model::CostModel},
|
||||||
accounts_background_service::AbsRequestSender, bank::Bank, bank_forks::BankForks,
|
|
||||||
cost_model::CostModel,
|
|
||||||
},
|
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
compute_budget::ComputeBudgetInstruction,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
signature::{Keypair, Signature},
|
message::Message,
|
||||||
system_transaction,
|
pubkey::{self, Pubkey},
|
||||||
|
signature::{Keypair, Signature, Signer},
|
||||||
|
system_instruction, system_transaction,
|
||||||
timing::{duration_as_us, timestamp},
|
timing::{duration_as_us, timestamp},
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
},
|
},
|
||||||
|
@ -36,6 +36,12 @@ use {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// transfer transaction cost = 1 * SIGNATURE_COST +
|
||||||
|
// 2 * WRITE_LOCK_UNITS +
|
||||||
|
// 1 * system_program
|
||||||
|
// = 1470 CU
|
||||||
|
const TRANSFER_TRANSACTION_COST: u32 = 1470;
|
||||||
|
|
||||||
fn check_txs(
|
fn check_txs(
|
||||||
receiver: &Arc<Receiver<WorkingBankEntry>>,
|
receiver: &Arc<Receiver<WorkingBankEntry>>,
|
||||||
ref_tx_count: usize,
|
ref_tx_count: usize,
|
||||||
|
@ -96,23 +102,44 @@ fn make_accounts_txs(
|
||||||
packets_per_batch: usize,
|
packets_per_batch: usize,
|
||||||
hash: Hash,
|
hash: Hash,
|
||||||
contention: WriteLockContention,
|
contention: WriteLockContention,
|
||||||
|
simulate_mint: bool,
|
||||||
|
mint_txs_percentage: usize,
|
||||||
) -> Vec<Transaction> {
|
) -> Vec<Transaction> {
|
||||||
use solana_sdk::pubkey;
|
|
||||||
let to_pubkey = pubkey::new_rand();
|
let to_pubkey = pubkey::new_rand();
|
||||||
let chunk_pubkeys: Vec<pubkey::Pubkey> = (0..total_num_transactions / packets_per_batch)
|
let chunk_pubkeys: Vec<pubkey::Pubkey> = (0..total_num_transactions / packets_per_batch)
|
||||||
.map(|_| pubkey::new_rand())
|
.map(|_| pubkey::new_rand())
|
||||||
.collect();
|
.collect();
|
||||||
let payer_key = Keypair::new();
|
let payer_key = Keypair::new();
|
||||||
let dummy = system_transaction::transfer(&payer_key, &to_pubkey, 1, hash);
|
|
||||||
(0..total_num_transactions)
|
(0..total_num_transactions)
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let mut new = dummy.clone();
|
let is_simulated_mint = is_simulated_mint_transaction(
|
||||||
|
simulate_mint,
|
||||||
|
i,
|
||||||
|
packets_per_batch,
|
||||||
|
mint_txs_percentage,
|
||||||
|
);
|
||||||
|
// simulated mint transactions have higher compute-unit-price
|
||||||
|
let compute_unit_price = if is_simulated_mint { 5 } else { 1 };
|
||||||
|
let mut new = make_transfer_transaction_with_compute_unit_price(
|
||||||
|
&payer_key,
|
||||||
|
&to_pubkey,
|
||||||
|
1,
|
||||||
|
hash,
|
||||||
|
compute_unit_price,
|
||||||
|
);
|
||||||
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen::<u8>()).collect();
|
let sig: Vec<u8> = (0..64).map(|_| thread_rng().gen::<u8>()).collect();
|
||||||
new.message.account_keys[0] = pubkey::new_rand();
|
new.message.account_keys[0] = pubkey::new_rand();
|
||||||
new.message.account_keys[1] = match contention {
|
new.message.account_keys[1] = match contention {
|
||||||
WriteLockContention::None => pubkey::new_rand(),
|
WriteLockContention::None => pubkey::new_rand(),
|
||||||
WriteLockContention::SameBatchOnly => chunk_pubkeys[i / packets_per_batch],
|
WriteLockContention::SameBatchOnly => {
|
||||||
|
// simulated mint transactions have conflict accounts
|
||||||
|
if is_simulated_mint {
|
||||||
|
chunk_pubkeys[i / packets_per_batch]
|
||||||
|
} else {
|
||||||
|
pubkey::new_rand()
|
||||||
|
}
|
||||||
|
}
|
||||||
WriteLockContention::Full => to_pubkey,
|
WriteLockContention::Full => to_pubkey,
|
||||||
};
|
};
|
||||||
new.signatures = vec![Signature::new(&sig[0..64])];
|
new.signatures = vec![Signature::new(&sig[0..64])];
|
||||||
|
@ -121,6 +148,35 @@ fn make_accounts_txs(
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In simulating mint, `mint_txs_percentage` transactions in a batch are mint transaction
|
||||||
|
// (eg., have conflicting account and higher priority) and remaining percentage regular
|
||||||
|
// transactions (eg., non-conflict and low priority)
|
||||||
|
fn is_simulated_mint_transaction(
|
||||||
|
simulate_mint: bool,
|
||||||
|
index: usize,
|
||||||
|
packets_per_batch: usize,
|
||||||
|
mint_txs_percentage: usize,
|
||||||
|
) -> bool {
|
||||||
|
simulate_mint && (index % packets_per_batch <= packets_per_batch * mint_txs_percentage / 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_transfer_transaction_with_compute_unit_price(
|
||||||
|
from_keypair: &Keypair,
|
||||||
|
to: &Pubkey,
|
||||||
|
lamports: u64,
|
||||||
|
recent_blockhash: Hash,
|
||||||
|
compute_unit_price: u64,
|
||||||
|
) -> Transaction {
|
||||||
|
let from_pubkey = from_keypair.pubkey();
|
||||||
|
let instructions = vec![
|
||||||
|
system_instruction::transfer(&from_pubkey, to, lamports),
|
||||||
|
ComputeBudgetInstruction::set_compute_unit_price(compute_unit_price),
|
||||||
|
ComputeBudgetInstruction::set_compute_unit_limit(TRANSFER_TRANSACTION_COST),
|
||||||
|
];
|
||||||
|
let message = Message::new(&instructions, Some(&from_pubkey));
|
||||||
|
Transaction::new(&[from_keypair], message, recent_blockhash)
|
||||||
|
}
|
||||||
|
|
||||||
struct PacketsPerIteration {
|
struct PacketsPerIteration {
|
||||||
packet_batches: Vec<PacketBatch>,
|
packet_batches: Vec<PacketBatch>,
|
||||||
transactions: Vec<Transaction>,
|
transactions: Vec<Transaction>,
|
||||||
|
@ -133,6 +189,8 @@ impl PacketsPerIteration {
|
||||||
batches_per_iteration: usize,
|
batches_per_iteration: usize,
|
||||||
genesis_hash: Hash,
|
genesis_hash: Hash,
|
||||||
write_lock_contention: WriteLockContention,
|
write_lock_contention: WriteLockContention,
|
||||||
|
simulate_mint: bool,
|
||||||
|
mint_txs_percentage: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let total_num_transactions = packets_per_batch * batches_per_iteration;
|
let total_num_transactions = packets_per_batch * batches_per_iteration;
|
||||||
let transactions = make_accounts_txs(
|
let transactions = make_accounts_txs(
|
||||||
|
@ -140,6 +198,8 @@ impl PacketsPerIteration {
|
||||||
packets_per_batch,
|
packets_per_batch,
|
||||||
genesis_hash,
|
genesis_hash,
|
||||||
write_lock_contention,
|
write_lock_contention,
|
||||||
|
simulate_mint,
|
||||||
|
mint_txs_percentage,
|
||||||
);
|
);
|
||||||
|
|
||||||
let packet_batches: Vec<PacketBatch> = to_packet_batches(&transactions, packets_per_batch);
|
let packet_batches: Vec<PacketBatch> = to_packet_batches(&transactions, packets_per_batch);
|
||||||
|
@ -219,6 +279,19 @@ fn main() {
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Disable forwarding messages to TPU using QUIC"),
|
.help("Disable forwarding messages to TPU using QUIC"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("simulate_mint")
|
||||||
|
.long("simulate-mint")
|
||||||
|
.takes_value(false)
|
||||||
|
.help("Simulate mint transactions to have higher priority"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("mint_txs_percentage")
|
||||||
|
.long("mint-txs-percentage")
|
||||||
|
.takes_value(true)
|
||||||
|
.requires("simulate_mint")
|
||||||
|
.help("In simulating mint, number of mint transactions out of 100."),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let num_banking_threads = matches
|
let num_banking_threads = matches
|
||||||
|
@ -236,6 +309,9 @@ fn main() {
|
||||||
let write_lock_contention = matches
|
let write_lock_contention = matches
|
||||||
.value_of_t::<WriteLockContention>("write_lock_contention")
|
.value_of_t::<WriteLockContention>("write_lock_contention")
|
||||||
.unwrap_or(WriteLockContention::None);
|
.unwrap_or(WriteLockContention::None);
|
||||||
|
let mint_txs_percentage = matches
|
||||||
|
.value_of_t::<usize>("mint_txs_percentage")
|
||||||
|
.unwrap_or(99);
|
||||||
|
|
||||||
let mint_total = 1_000_000_000_000;
|
let mint_total = 1_000_000_000_000;
|
||||||
let GenesisConfigInfo {
|
let GenesisConfigInfo {
|
||||||
|
@ -263,6 +339,8 @@ fn main() {
|
||||||
batches_per_iteration,
|
batches_per_iteration,
|
||||||
genesis_config.hash(),
|
genesis_config.hash(),
|
||||||
write_lock_contention,
|
write_lock_contention,
|
||||||
|
matches.is_present("simulate_mint"),
|
||||||
|
mint_txs_percentage,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.take(num_chunks)
|
.take(num_chunks)
|
||||||
|
@ -329,12 +407,8 @@ fn main() {
|
||||||
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
Blockstore::open(&ledger_path).expect("Expected to be able to open database ledger"),
|
||||||
);
|
);
|
||||||
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||||
let (exit, poh_recorder, poh_service, signal_receiver) = create_test_recorder(
|
let (exit, poh_recorder, poh_service, signal_receiver) =
|
||||||
&bank,
|
create_test_recorder(&bank, &blockstore, None, Some(leader_schedule_cache));
|
||||||
&blockstore,
|
|
||||||
None,
|
|
||||||
Some(leader_schedule_cache.clone()),
|
|
||||||
);
|
|
||||||
let cluster_info = ClusterInfo::new(
|
let cluster_info = ClusterInfo::new(
|
||||||
Node::new_localhost().info,
|
Node::new_localhost().info,
|
||||||
Arc::new(Keypair::new()),
|
Arc::new(Keypair::new()),
|
||||||
|
@ -370,7 +444,6 @@ fn main() {
|
||||||
let mut tx_total_us = 0;
|
let mut tx_total_us = 0;
|
||||||
let base_tx_count = bank.transaction_count();
|
let base_tx_count = bank.transaction_count();
|
||||||
let mut txs_processed = 0;
|
let mut txs_processed = 0;
|
||||||
let mut root = 1;
|
|
||||||
let collector = solana_sdk::pubkey::new_rand();
|
let collector = solana_sdk::pubkey::new_rand();
|
||||||
let mut total_sent = 0;
|
let mut total_sent = 0;
|
||||||
for current_iteration_index in 0..iterations {
|
for current_iteration_index in 0..iterations {
|
||||||
|
@ -404,18 +477,22 @@ fn main() {
|
||||||
sleep(Duration::from_millis(5));
|
sleep(Duration::from_millis(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if txs had been processed by bank. Returns when all transactions are
|
||||||
|
// processed, with `FALSE` indicate there is still bank. or returns TRUE indicate a
|
||||||
|
// bank has expired before receiving all txs.
|
||||||
if check_txs(
|
if check_txs(
|
||||||
&signal_receiver,
|
&signal_receiver,
|
||||||
packets_for_this_iteration.transactions.len(),
|
packets_for_this_iteration.transactions.len(),
|
||||||
&poh_recorder,
|
&poh_recorder,
|
||||||
) {
|
) {
|
||||||
debug!(
|
eprintln!(
|
||||||
"resetting bank {} tx count: {} txs_proc: {}",
|
"[iteration {}, tx sent {}, slot {} expired, bank tx count {}]",
|
||||||
|
current_iteration_index,
|
||||||
|
sent,
|
||||||
bank.slot(),
|
bank.slot(),
|
||||||
bank.transaction_count(),
|
bank.transaction_count(),
|
||||||
txs_processed
|
|
||||||
);
|
);
|
||||||
txs_processed = bank.transaction_count();
|
|
||||||
tx_total_us += duration_as_us(&now.elapsed());
|
tx_total_us += duration_as_us(&now.elapsed());
|
||||||
|
|
||||||
let mut poh_time = Measure::start("poh_time");
|
let mut poh_time = Measure::start("poh_time");
|
||||||
|
@ -443,14 +520,6 @@ fn main() {
|
||||||
|
|
||||||
poh_recorder.write().unwrap().set_bank(&bank, false);
|
poh_recorder.write().unwrap().set_bank(&bank, false);
|
||||||
assert!(poh_recorder.read().unwrap().bank().is_some());
|
assert!(poh_recorder.read().unwrap().bank().is_some());
|
||||||
if bank.slot() > 32 {
|
|
||||||
leader_schedule_cache.set_root(&bank);
|
|
||||||
bank_forks
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.set_root(root, &AbsRequestSender::default(), None);
|
|
||||||
root += 1;
|
|
||||||
}
|
|
||||||
debug!(
|
debug!(
|
||||||
"new_bank_time: {}us insert_time: {}us poh_time: {}us",
|
"new_bank_time: {}us insert_time: {}us poh_time: {}us",
|
||||||
new_bank_time.as_us(),
|
new_bank_time.as_us(),
|
||||||
|
@ -458,6 +527,13 @@ fn main() {
|
||||||
poh_time.as_us(),
|
poh_time.as_us(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"[iteration {}, tx sent {}, slot {} active, bank tx count {}]",
|
||||||
|
current_iteration_index,
|
||||||
|
sent,
|
||||||
|
bank.slot(),
|
||||||
|
bank.transaction_count(),
|
||||||
|
);
|
||||||
tx_total_us += duration_as_us(&now.elapsed());
|
tx_total_us += duration_as_us(&now.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,27 +542,25 @@ fn main() {
|
||||||
// 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();
|
||||||
total_us += duration_as_us(&now.elapsed());
|
total_us += duration_as_us(&now.elapsed());
|
||||||
debug!(
|
|
||||||
"time: {} us checked: {} sent: {}",
|
|
||||||
duration_as_us(&now.elapsed()),
|
|
||||||
total_num_transactions / num_chunks as u64,
|
|
||||||
sent,
|
|
||||||
);
|
|
||||||
total_sent += sent;
|
total_sent += sent;
|
||||||
|
|
||||||
if current_iteration_index % 16 == 0 {
|
if current_iteration_index % num_chunks == 0 {
|
||||||
let last_blockhash = bank.last_blockhash();
|
let last_blockhash = bank.last_blockhash();
|
||||||
for packets_for_single_iteration in all_packets.iter_mut() {
|
for packets_for_single_iteration in all_packets.iter_mut() {
|
||||||
packets_for_single_iteration.refresh_blockhash(last_blockhash);
|
packets_for_single_iteration.refresh_blockhash(last_blockhash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let txs_processed = bank_forks
|
txs_processed += bank_forks
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.working_bank()
|
.working_bank()
|
||||||
.transaction_count();
|
.transaction_count();
|
||||||
debug!("processed: {} base: {}", txs_processed, base_tx_count);
|
debug!("processed: {} base: {}", txs_processed, base_tx_count);
|
||||||
|
|
||||||
|
eprintln!("[total_sent: {}, base_tx_count: {}, txs_processed: {}, txs_landed: {}, total_us: {}, tx_total_us: {}]",
|
||||||
|
total_sent, base_tx_count, txs_processed, (txs_processed - base_tx_count), total_us, tx_total_us);
|
||||||
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{{'name': 'banking_bench_total', 'median': '{:.2}'}}",
|
"{{'name': 'banking_bench_total', 'median': '{:.2}'}}",
|
||||||
(1000.0 * 1000.0 * total_sent as f64) / (total_us as f64),
|
(1000.0 * 1000.0 * total_sent as f64) / (total_us as f64),
|
||||||
|
|
Loading…
Reference in New Issue