Merge pull request #375 from blockworks-foundation/lou/bench-helpers

refactor: use VersionedTransaction in benchmarks
This commit is contained in:
Lou-Kamades 2024-03-27 14:13:31 -04:00 committed by GitHub
commit bc096d165c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 57 additions and 168 deletions

View File

@ -1,4 +1,5 @@
use crate::{helpers::BenchHelper, metrics::Metric, metrics::TxMetricData};
use crate::{create_memo_tx_large, create_memo_tx_small, generate_random_strings};
use crate::{metrics::Metric, metrics::TxMetricData};
use dashmap::DashMap;
use log::warn;
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
@ -53,20 +54,20 @@ pub async fn bench(
TransactionSize::Small => 10,
TransactionSize::Large => 232, // 565 is max but we need to lower that to not burn the CUs
};
let rand_strings = BenchHelper::generate_random_strings(tx_count, Some(seed), n_chars);
let rand_strings = generate_random_strings(tx_count, Some(seed), n_chars);
let bench_start_time = Instant::now();
for rand_string in &rand_strings {
let blockhash = { *block_hash.read().await };
let tx = match transaction_size {
TransactionSize::Small => BenchHelper::create_memo_tx_small(
TransactionSize::Small => create_memo_tx_small(
rand_string,
&funded_payer,
blockhash,
cu_price_micro_lamports,
),
TransactionSize::Large => BenchHelper::create_memo_tx_large(
TransactionSize::Large => create_memo_tx_large(
rand_string,
&funded_payer,
blockhash,

View File

@ -11,7 +11,7 @@ use log::{debug, info, warn};
use solana_lite_rpc_util::obfuscate_rpcurl;
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::signature::{read_keypair_file, Signature, Signer};
use solana_sdk::transaction::Transaction;
use solana_sdk::transaction::VersionedTransaction;
use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair};
use tokio::time::{sleep, Instant};
use url::Url;
@ -146,7 +146,7 @@ async fn create_tx(
payer: &Keypair,
rng: &mut Rng8,
tx_params: &BenchmarkTransactionParams,
) -> anyhow::Result<Transaction> {
) -> anyhow::Result<VersionedTransaction> {
let (blockhash, _) = rpc
.get_latest_blockhash_with_commitment(CommitmentConfig::confirmed())
.await?;
@ -156,7 +156,7 @@ async fn create_tx(
async fn send_and_confirm_transaction(
rpc: &RpcClient,
tx: Transaction,
tx: VersionedTransaction,
max_timeout: Duration,
) -> anyhow::Result<ConfirmationResponseFromRpc> {
let result_vec: Vec<(Signature, ConfirmationResponseFromRpc)> =

View File

@ -10,7 +10,7 @@ use solana_rpc_client_api::config::RpcSendTransactionConfig;
use solana_sdk::clock::Slot;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::signature::Signature;
use solana_sdk::transaction::Transaction;
use solana_sdk::transaction::VersionedTransaction;
use solana_transaction_status::TransactionConfirmationStatus;
use std::collections::{HashMap, HashSet};
use std::iter::zip;
@ -36,7 +36,7 @@ pub enum ConfirmationResponseFromRpc {
pub async fn send_and_confirm_bulk_transactions(
rpc_client: &RpcClient,
txs: &[Transaction],
txs: &[VersionedTransaction],
max_timeout: Duration,
) -> anyhow::Result<Vec<(Signature, ConfirmationResponseFromRpc)>> {
trace!("Polling for next slot ..");

View File

@ -1,14 +1,10 @@
use anyhow::Context;
use itertools::Itertools;
use lazy_static::lazy_static;
use rand::{distributions::Alphanumeric, prelude::Distribution, SeedableRng};
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::compute_budget;
use solana_sdk::instruction::AccountMeta;
use solana_sdk::{
commitment_config::CommitmentConfig,
hash::Hash,
instruction::Instruction,
message::Message,
pubkey::Pubkey,
signature::{Keypair, Signature},
@ -17,10 +13,9 @@ use solana_sdk::{
transaction::Transaction,
};
use std::path::PathBuf;
use std::{str::FromStr, time::Duration};
use std::time::Duration;
use tokio::time::Instant;
const MEMO_PROGRAM_ID: &str = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
const WAIT_LIMIT_IN_SECONDS: u64 = 60;
lazy_static! {
@ -77,132 +72,4 @@ impl BenchHelper {
Transaction::new(&[funded_payer], message, blockhash)
}
pub fn generate_random_strings(
num_of_txs: usize,
random_seed: Option<u64>,
n_chars: usize,
) -> Vec<Vec<u8>> {
let seed = random_seed.map_or(0, |x| x);
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
(0..num_of_txs)
.map(|_| Alphanumeric.sample_iter(&mut rng).take(n_chars).collect())
.collect()
}
#[inline]
pub fn generate_txs(
num_of_txs: usize,
funded_payer: &Keypair,
blockhash: Hash,
random_seed: Option<u64>,
cu_price_micro_lamports: u64,
) -> Vec<Transaction> {
let seed = random_seed.map_or(0, |x| x);
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
(0..num_of_txs)
.map(|_| {
let random_bytes: Vec<u8> = Alphanumeric.sample_iter(&mut rng).take(10).collect();
Self::create_memo_tx_small(
&random_bytes,
funded_payer,
blockhash,
cu_price_micro_lamports,
)
})
.collect()
}
// note: there is another version of this
pub fn create_memo_tx_small(
msg: &[u8],
payer: &Keypair,
blockhash: Hash,
cu_price_micro_lamports: u64,
) -> Transaction {
let memo = Pubkey::from_str(MEMO_PROGRAM_ID).unwrap();
let instruction = Instruction::new_with_bytes(memo, msg, vec![]);
let cu_request: Instruction =
compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(14000);
let instructions = if cu_price_micro_lamports > 0 {
let cu_budget_ix: Instruction =
compute_budget::ComputeBudgetInstruction::set_compute_unit_price(
cu_price_micro_lamports,
);
vec![cu_request, cu_budget_ix, instruction]
} else {
vec![cu_request, instruction]
};
let message = Message::new(&instructions, Some(&payer.pubkey()));
Transaction::new(&[payer], message, blockhash)
}
pub fn create_memo_tx_large(
msg: &[u8],
payer: &Keypair,
blockhash: Hash,
cu_price_micro_lamports: u64,
) -> Transaction {
let accounts = (0..8).map(|_| Keypair::new()).collect_vec();
let memo = Pubkey::from_str(MEMO_PROGRAM_ID).unwrap();
let instruction = Instruction::new_with_bytes(
memo,
msg,
accounts
.iter()
.map(|keypair| AccountMeta::new_readonly(keypair.pubkey(), true))
.collect_vec(),
);
let instructions = if cu_price_micro_lamports > 0 {
let cu_budget_ix: Instruction =
compute_budget::ComputeBudgetInstruction::set_compute_unit_price(
cu_price_micro_lamports,
);
vec![cu_budget_ix, instruction]
} else {
vec![instruction]
};
let message = Message::new(&instructions, Some(&payer.pubkey()));
let mut signers = vec![payer];
signers.extend(accounts.iter());
Transaction::new(&signers, message, blockhash)
}
}
#[test]
fn transaction_size_small() {
let blockhash = Hash::default();
let payer_keypair = Keypair::from_base58_string(
"rKiJ7H5UUp3JR18kNyTF1XPuwPKHEM7gMLWHZPWP5djrW1vSjfwjhvJrevxF9MPmUmN9gJMLHZdLMgc9ao78eKr",
);
let seed = 42;
let random_strings = BenchHelper::generate_random_strings(1, Some(seed), 10);
let rand_string = random_strings.first().unwrap();
let tx = BenchHelper::create_memo_tx_small(rand_string, &payer_keypair, blockhash, 300);
assert_eq!(bincode::serialized_size(&tx).unwrap(), 231);
}
#[test]
fn transaction_size_large() {
let blockhash = Hash::default();
let payer_keypair = Keypair::from_base58_string(
"rKiJ7H5UUp3JR18kNyTF1XPuwPKHEM7gMLWHZPWP5djrW1vSjfwjhvJrevxF9MPmUmN9gJMLHZdLMgc9ao78eKr",
);
let seed = 42;
let random_strings = BenchHelper::generate_random_strings(1, Some(seed), 232);
let rand_string = random_strings.first().unwrap();
let tx = BenchHelper::create_memo_tx_large(rand_string, &payer_keypair, blockhash, 300);
assert_eq!(bincode::serialized_size(&tx).unwrap(), 1222);
}

View File

@ -6,6 +6,8 @@ use log::{debug, warn};
use rand::{distributions::Alphanumeric, prelude::Distribution, SeedableRng};
use solana_rpc_client::{nonblocking::rpc_client::RpcClient, rpc_client::SerializableTransaction};
use solana_sdk::compute_budget::ComputeBudgetInstruction;
use solana_sdk::message::v0;
use solana_sdk::transaction::VersionedTransaction;
use solana_sdk::{
commitment_config::CommitmentConfig,
hash::Hash,
@ -189,6 +191,19 @@ pub fn generate_random_string(rng: &mut Rng8, n_chars: usize) -> Vec<u8> {
Alphanumeric.sample_iter(rng).take(n_chars).collect()
}
#[inline]
pub fn generate_random_strings(
num_of_txs: usize,
random_seed: Option<u64>,
n_chars: usize,
) -> Vec<Vec<u8>> {
let seed = random_seed.map_or(0, |x| x);
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
(0..num_of_txs)
.map(|_| Alphanumeric.sample_iter(&mut rng).take(n_chars).collect())
.collect()
}
#[inline]
pub fn generate_txs(
num_of_txs: usize,
@ -196,7 +211,7 @@ pub fn generate_txs(
blockhash: Hash,
rng: &mut Rng8,
tx_params: &BenchmarkTransactionParams,
) -> Vec<Transaction> {
) -> Vec<VersionedTransaction> {
(0..num_of_txs)
.map(|_| create_memo_tx(payer, blockhash, rng, tx_params))
.collect()
@ -207,7 +222,7 @@ pub fn create_memo_tx(
blockhash: Hash,
rng: &mut Rng8,
tx_params: &BenchmarkTransactionParams,
) -> Transaction {
) -> VersionedTransaction {
let rand_str = generate_random_string(rng, tx_params.tx_size.memo_size());
match tx_params.tx_size {
@ -231,19 +246,22 @@ pub fn create_memo_tx_small(
payer: &Keypair,
blockhash: Hash,
cu_price_micro_lamports: u64,
) -> Transaction {
) -> VersionedTransaction {
let memo = Pubkey::from_str(MEMO_PROGRAM_ID).unwrap();
let cu_budget_ix: Instruction =
ComputeBudgetInstruction::set_compute_unit_price(cu_price_micro_lamports);
// Program consumed: 12775 of 13700 compute units
let cu_limit_ix: Instruction = ComputeBudgetInstruction::set_compute_unit_limit(14000);
let instruction = Instruction::new_with_bytes(memo, msg, vec![]);
let message = Message::new(
let message = v0::Message::try_compile(
&payer.pubkey(),
&[cu_budget_ix, cu_limit_ix, instruction],
Some(&payer.pubkey()),
);
Transaction::new(&[payer], message, blockhash)
&[],
blockhash,
)
.unwrap();
let versioned_message = solana_sdk::message::VersionedMessage::V0(message);
VersionedTransaction::try_new(versioned_message, &[&payer]).unwrap()
}
pub fn create_memo_tx_large(
@ -251,7 +269,7 @@ pub fn create_memo_tx_large(
payer: &Keypair,
blockhash: Hash,
cu_price_micro_lamports: u64,
) -> Transaction {
) -> VersionedTransaction {
let accounts = (0..8).map(|_| Keypair::new()).collect_vec();
let memo = Pubkey::from_str(MEMO_PROGRAM_ID).unwrap();
@ -267,15 +285,18 @@ pub fn create_memo_tx_large(
.map(|keypair| AccountMeta::new_readonly(keypair.pubkey(), true))
.collect_vec(),
);
let message = Message::new(
let message = v0::Message::try_compile(
&payer.pubkey(),
&[cu_budget_ix, cu_limit_ix, instruction],
Some(&payer.pubkey()),
);
&[],
blockhash,
)
.unwrap();
let versioned_message = solana_sdk::message::VersionedMessage::V0(message);
let mut signers = vec![payer];
signers.extend(accounts.iter());
Transaction::new(&signers, message, blockhash)
VersionedTransaction::try_new(versioned_message, &signers).unwrap()
}
#[test]
@ -284,12 +305,12 @@ fn transaction_size_small() {
let payer_keypair = Keypair::from_base58_string(
"rKiJ7H5UUp3JR18kNyTF1XPuwPKHEM7gMLWHZPWP5djrW1vSjfwjhvJrevxF9MPmUmN9gJMLHZdLMgc9ao78eKr",
);
let mut rng = create_rng(Some(42));
let rand_string = generate_random_string(&mut rng, 10);
let priority_fee = 100;
let seed = 42;
let random_strings = generate_random_strings(1, Some(seed), 10);
let rand_string = random_strings.first().unwrap();
let tx = create_memo_tx_small(rand_string, &payer_keypair, blockhash, 300);
let tx = create_memo_tx_small(&rand_string, &payer_keypair, blockhash, priority_fee);
assert_eq!(bincode::serialized_size(&tx).unwrap(), 231);
assert_eq!(bincode::serialized_size(&tx).unwrap(), 233);
}
#[test]
@ -298,10 +319,10 @@ fn transaction_size_large() {
let payer_keypair = Keypair::from_base58_string(
"rKiJ7H5UUp3JR18kNyTF1XPuwPKHEM7gMLWHZPWP5djrW1vSjfwjhvJrevxF9MPmUmN9gJMLHZdLMgc9ao78eKr",
);
let mut rng = create_rng(Some(42));
let rand_string = generate_random_string(&mut rng, 240);
let priority_fee = 100;
let seed = 42;
let random_strings = generate_random_strings(1, Some(seed), 232);
let rand_string = random_strings.first().unwrap();
let tx = create_memo_tx_large(rand_string, &payer_keypair, blockhash, 300);
let tx = create_memo_tx_large(&rand_string, &payer_keypair, blockhash, priority_fee);
assert_eq!(bincode::serialized_size(&tx).unwrap(), 1238);
assert_eq!(bincode::serialized_size(&tx).unwrap(), 1232);
}