Skip to content

Commit

Permalink
A benchmark suite for the getTransaction RPC call (#3987)
Browse files Browse the repository at this point in the history
* Track the signatures of transactions created by the bench runner

* A benchmark suite for the `getTransaction` RPC call
  • Loading branch information
steveluscher authored Dec 9, 2024
1 parent 6bb3a03 commit a826581
Showing 1 changed file with 103 additions and 3 deletions.
106 changes: 103 additions & 3 deletions accounts-cluster-bench/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use {
hidden_unless_forced, input_parsers::pubkey_of, input_validators::is_url_or_moniker,
},
solana_cli_config::{ConfigInput, CONFIG_FILE},
solana_client::transaction_executor::TransactionExecutor,
solana_client::{
rpc_client::SerializableTransaction, transaction_executor::TransactionExecutor,
},
solana_gossip::gossip_service::discover,
solana_inline_spl::token,
solana_measure::measure::Measure,
Expand All @@ -21,19 +23,22 @@ use {
message::Message,
program_pack::Pack,
pubkey::Pubkey,
signature::{read_keypair_file, Keypair, Signer},
signature::{read_keypair_file, Keypair, Signature, Signer},
system_instruction, system_program,
transaction::Transaction,
},
solana_streamer::socket::SocketAddrSpace,
solana_transaction_status::UiTransactionEncoding,
spl_token::state::Account,
std::{
cmp::min,
collections::VecDeque,
ops::Deref,
process::exit,
str::FromStr,
sync::{
atomic::{AtomicBool, AtomicU64, Ordering},
Arc, Barrier,
Arc, Barrier, RwLock,
},
thread::{sleep, Builder, JoinHandle},
time::{Duration, Instant},
Expand Down Expand Up @@ -132,6 +137,35 @@ struct SeedTracker {
max_closed: Arc<AtomicU64>,
}

#[derive(Clone)]
struct TransactionSignatureTracker(Arc<RwLock<VecDeque<Signature>>>);

impl TransactionSignatureTracker {
fn get_random(&self) -> Option<Signature> {
let signatures = self.read().unwrap();
if signatures.is_empty() {
None
} else {
let random_index = thread_rng().gen_range(0..signatures.len());
let random_signature = signatures.get(random_index);
random_signature.cloned()
}
}
fn track_transactions(&self, transactions: &[Transaction]) {
let mut lock = self.write().unwrap();
for signature in transactions.iter().map(Transaction::get_signature) {
lock.push_back(*signature);
}
}
}

impl Deref for TransactionSignatureTracker {
type Target = Arc<RwLock<VecDeque<Signature>>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}

fn make_create_message(
keypair: &Keypair,
base_keypair: &Keypair,
Expand Down Expand Up @@ -257,6 +291,8 @@ pub enum RpcBench {
Supply,
TokenAccountsByDelegate,
AccountInfo,
Transaction,
TransactionParsed,
FirstAvailableBlock,
}

Expand All @@ -277,6 +313,8 @@ impl FromStr for RpcBench {
"multiple-accounts" => Ok(RpcBench::MultipleAccounts),
"token-accounts-by-delegate" => Ok(RpcBench::TokenAccountsByDelegate),
"token-accounts-by-owner" => Ok(RpcBench::TokenAccountsByOwner),
"transaction" => Ok(RpcBench::Transaction),
"transaction-parsed" => Ok(RpcBench::TransactionParsed),
"version" => Ok(RpcBench::Version),
_ => Err(RpcParseError::InvalidOption),
}
Expand Down Expand Up @@ -337,6 +375,37 @@ fn process_get_multiple_accounts(
}
}

fn process_get_transaction(
test_name: &'static str,
transaction_signature_tracker: &TransactionSignatureTracker,
client: &RpcClient,
stats: &mut RpcBenchStats,
last_error: &mut Instant,
encoding: UiTransactionEncoding,
) {
let Some(signature) = transaction_signature_tracker.get_random() else {
info!("transaction: No transactions have yet been made; skipping");
return;
};
let mut measure = Measure::start(test_name);
match client.get_transaction(&signature, encoding) {
Ok(_tx) => {
measure.stop();
stats.success += 1;
stats.total_success_time_us += measure.as_us();
}
Err(e) => {
measure.stop();
stats.errors += 1;
stats.total_errors_time_us += measure.as_us();
if last_error.elapsed().as_secs() > 2 {
info!("get_transaction error: {:?}", &e);
*last_error = Instant::now();
}
}
};
}

#[derive(Default)]
struct RpcBenchStats {
errors: u64,
Expand All @@ -345,6 +414,7 @@ struct RpcBenchStats {
total_success_time_us: u64,
}

#[allow(clippy::too_many_arguments)]
fn run_rpc_bench_loop(
rpc_bench: RpcBench,
thread: usize,
Expand All @@ -355,6 +425,7 @@ fn run_rpc_bench_loop(
max_closed: &AtomicU64,
max_created: &AtomicU64,
mint: &Option<Pubkey>,
transaction_signature_tracker: &TransactionSignatureTracker,
) {
let mut stats = RpcBenchStats::default();
let mut iters = 0;
Expand Down Expand Up @@ -553,6 +624,26 @@ fn run_rpc_bench_loop(
}
}
}
RpcBench::Transaction => {
process_get_transaction(
"rpc-get-transaction-base64",
transaction_signature_tracker,
client,
&mut stats,
&mut last_error,
UiTransactionEncoding::Base64,
);
}
RpcBench::TransactionParsed => {
process_get_transaction(
"rpc-get-transaction-parsed",
transaction_signature_tracker,
client,
&mut stats,
&mut last_error,
UiTransactionEncoding::JsonParsed,
);
}
RpcBench::Version => {
let mut rpc_time = Measure::start("rpc-get-version");
match client.get_version() {
Expand Down Expand Up @@ -587,6 +678,7 @@ fn make_rpc_bench_threads(
seed_tracker: &SeedTracker,
base_keypair_pubkey: Pubkey,
num_rpc_bench_threads: usize,
transaction_signature_tracker: &TransactionSignatureTracker,
) -> Vec<JoinHandle<()>> {
let program_id = if mint.is_some() {
token::id()
Expand All @@ -602,6 +694,7 @@ fn make_rpc_bench_threads(
let exit = exit.clone();
let max_closed = seed_tracker.max_closed.clone();
let max_created = seed_tracker.max_created.clone();
let transaction_signature_tracker = transaction_signature_tracker.clone();
let mint = *mint;
Builder::new()
.name(format!("rpc-bench-{}", thread))
Expand All @@ -617,6 +710,7 @@ fn make_rpc_bench_threads(
&max_closed,
&max_created,
&mint,
&transaction_signature_tracker,
)
})
.unwrap()
Expand Down Expand Up @@ -670,6 +764,8 @@ fn run_accounts_bench(
max_created: Arc::new(AtomicU64::default()),
max_closed: Arc::new(AtomicU64::default()),
};
let transaction_signature_tracker =
TransactionSignatureTracker(Arc::new(RwLock::new(VecDeque::with_capacity(5000))));

info!("Starting balance(s): {:?}", balances);

Expand Down Expand Up @@ -709,6 +805,7 @@ fn run_accounts_bench(
&seed_tracker,
base_keypair_pubkey,
num_rpc_bench_threads,
&transaction_signature_tracker,
)
} else {
Vec::new()
Expand Down Expand Up @@ -771,6 +868,7 @@ fn run_accounts_bench(
.collect();
balances[i] = balances[i].saturating_sub(lamports * txs.len() as u64);
info!("txs: {}", txs.len());
transaction_signature_tracker.track_transactions(&txs);
let new_ids = executor.push_transactions(txs);
info!("ids: {}", new_ids.len());
tx_sent_count += new_ids.len();
Expand Down Expand Up @@ -804,6 +902,7 @@ fn run_accounts_bench(
.collect();
balances[0] = balances[0].saturating_sub(fee * txs.len() as u64);
info!("close txs: {}", txs.len());
transaction_signature_tracker.track_transactions(&txs);
let new_ids = executor.push_transactions(txs);
info!("close ids: {}", new_ids.len());
tx_sent_count += new_ids.len();
Expand Down Expand Up @@ -900,6 +999,7 @@ fn run_accounts_bench(
.collect();
balances[i] = balances[i].saturating_sub(fee * txs.len() as u64);
info!("close txs: {}", txs.len());
transaction_signature_tracker.track_transactions(&txs);
let new_ids = executor.push_transactions(txs);
info!("close ids: {}", new_ids.len());
tx_sent_count += new_ids.len();
Expand Down

0 comments on commit a826581

Please sign in to comment.