Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
consumer bench
Browse files Browse the repository at this point in the history
  • Loading branch information
apfitzge committed Apr 28, 2023
1 parent 6664493 commit e22981b
Showing 1 changed file with 163 additions and 0 deletions.
163 changes: 163 additions & 0 deletions core/benches/consumer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#![feature(test)]

use {
crossbeam_channel::{unbounded, Receiver},
rayon::{
iter::IndexedParallelIterator,
prelude::{IntoParallelIterator, ParallelIterator},
},
solana_core::{
banking_stage::{committer::Committer, consumer::Consumer},
qos_service::QosService,
},
solana_entry::entry::Entry,
solana_ledger::{
blockstore::Blockstore,
genesis_utils::{create_genesis_config, GenesisConfigInfo},
},
solana_poh::{
poh_recorder::{create_test_recorder, PohRecorder},
poh_service::PohService,
},
solana_runtime::bank::Bank,
solana_sdk::{signer::Signer, system_transaction, transaction::SanitizedTransaction},
std::sync::{
atomic::{AtomicBool, Ordering},
Arc, RwLock,
},
tempfile::TempDir,
};
extern crate test;

use {solana_sdk::signature::Keypair, test::Bencher};

fn create_accounts(num: usize) -> Vec<Keypair> {
(0..num).into_par_iter().map(|_| Keypair::new()).collect()
}

fn create_funded_accounts(mint_keypair: &Keypair, bank: &Bank, num: usize) -> Vec<Keypair> {
assert!(
num.is_power_of_two(),
"must be power of 2 for parallel funding tree"
);
let accounts = create_accounts(num);

// Create a funding tree so we can fund in parallel
let mut balance = 5100 * num as u64;
bank.transfer(balance, mint_keypair, &accounts[0].pubkey())
.unwrap();

let mut chunk_len = accounts.len();
while chunk_len > 0 {
(0..num).into_par_iter().step_by(chunk_len).for_each(|i| {
let from = &accounts[i];
let to = &accounts[i + chunk_len / 2].pubkey();
bank.transfer(balance / 2, from, to).unwrap();
});

chunk_len /= 2;
balance /= 2;
}

accounts
}

fn create_transactions(
mint_keypair: &Keypair,
bank: &Bank,
num: usize,
) -> Vec<SanitizedTransaction> {
let funded_accounts = create_funded_accounts(mint_keypair, bank, 2 * num);
funded_accounts
.into_par_iter()
.chunks(2)
.map(|chunk| {
let from = &chunk[0];
let to = &chunk[1];
system_transaction::transfer(from, &to.pubkey(), 1, bank.last_blockhash())
})
.map(SanitizedTransaction::from_transaction_for_tests)
.collect()
}

fn create_consumer(poh_recorder: &RwLock<PohRecorder>) -> Consumer {
let (replay_vote_sender, _replay_vote_receiver) = unbounded();
let committer = Committer::new(None, replay_vote_sender, Arc::default());
let transaction_recorder = poh_recorder.read().unwrap().new_recorder();
Consumer::new(committer, transaction_recorder, QosService::new(0), None)
}

struct BenchFrame {
mint_keypair: Keypair,
bank: Arc<Bank>,
_ledger_path: TempDir,
exit: Arc<AtomicBool>,
poh_recorder: Arc<RwLock<PohRecorder>>,
poh_service: PohService,
_signal_receiver: Receiver<(Arc<Bank>, (Entry, u64))>,
}

fn setup() -> BenchFrame {
let mint_total = u64::MAX;
let GenesisConfigInfo {
mut genesis_config,
mint_keypair,
..
} = create_genesis_config(mint_total);

// Set a high ticks_per_slot so we don't run out of ticks
// during the benchmark
genesis_config.ticks_per_slot = 10_000;

let mut bank = Bank::new_for_benches(&genesis_config);
// Allow arbitrary transaction processing time for the purposes of this bench
bank.ns_per_slot = u128::MAX;

// set cost tracker limits to MAX so it will not filter out TXs
bank.write_cost_tracker()
.unwrap()
.set_limits(std::u64::MAX, std::u64::MAX, std::u64::MAX);
let bank = Arc::new(bank);

let ledger_path = TempDir::new().unwrap();
let blockstore = Arc::new(
Blockstore::open(ledger_path.path()).expect("Expected to be able to open database ledger"),
);
let (exit, poh_recorder, poh_service, signal_receiver) =
create_test_recorder(&bank, blockstore, None, None);

BenchFrame {
mint_keypair,
bank,
_ledger_path: ledger_path,
exit,
poh_recorder,
poh_service,
_signal_receiver: signal_receiver,
}
}

#[bench]
fn bench_process_and_record_transactions(bencher: &mut Bencher) {
let BenchFrame {
mint_keypair,
bank,
_ledger_path,
exit,
poh_recorder,
poh_service,
..
} = setup();
let consumer = create_consumer(&poh_recorder);
let transactions = create_transactions(&mint_keypair, &bank, 2_usize.pow(20));

let mut transaction_iter = transactions.chunks(64);

println!("beginning bench...");
bencher.iter(move || {
consumer.process_and_record_transactions(&bank, transaction_iter.next().unwrap(), 0);
});

exit.store(true, Ordering::Relaxed);
poh_service.join().unwrap();
}

0 comments on commit e22981b

Please sign in to comment.