#![feature(test)]
extern crate test;
use {
bincode::serialize,
rand::{rngs::SmallRng, Rng, SeedableRng},
solana_accounts_db::ancestors::Ancestors,
solana_hash::{Hash, HASH_BYTES},
solana_runtime::{bank::BankStatusCache, status_cache::*},
solana_sha256_hasher::hash,
solana_signature::{Signature, SIGNATURE_BYTES},
test::Bencher,
};
#[bench]
fn bench_status_cache_serialize(bencher: &mut Bencher) {
let mut status_cache = BankStatusCache::default();
status_cache.add_root(0);
status_cache.clear();
for hash_index in 0..100 {
let blockhash = Hash::new_from_array([hash_index; HASH_BYTES]);
let mut id = blockhash;
for _ in 0..100 {
id = hash(id.as_ref());
let mut sigbytes = Vec::from(id.as_ref());
id = hash(id.as_ref());
sigbytes.extend(id.as_ref());
let sig = Signature::try_from(sigbytes).unwrap();
status_cache.insert(&blockhash, sig, 0, Ok(()));
}
}
assert!(status_cache.roots().contains(&0));
bencher.iter(|| {
let _ = serialize(&status_cache.root_slot_deltas()).unwrap();
});
}
#[bench]
fn bench_status_cache_serialize_max(bencher: &mut Bencher) {
let max_cache_entries = MAX_CACHE_ENTRIES as u64;
let mut status_cache = BankStatusCache::default();
fill_status_cache(&mut status_cache, max_cache_entries, 100_000);
assert!(status_cache.roots().contains(&0));
bencher.iter(|| {
let _ = serialize(&status_cache.root_slot_deltas()).unwrap();
});
}
#[bench]
fn bench_status_cache_root_slot_deltas(bencher: &mut Bencher) {
let mut status_cache = BankStatusCache::default();
let slots: Vec<_> = (42..).take(MAX_CACHE_ENTRIES).collect();
for slot in &slots {
for _ in 0..5 {
status_cache.insert(&Hash::new_unique(), Hash::new_unique(), *slot, Ok(()));
}
status_cache.add_root(*slot);
}
bencher.iter(|| test::black_box(status_cache.root_slot_deltas()));
}
fn fill_status_cache(status_cache: &mut BankStatusCache, max_cache_entries: u64, num_txs: usize) {
for slot in 0..max_cache_entries {
let blockhash = Hash::new_unique();
fill_status_cache_slot(status_cache, &blockhash, slot, num_txs);
}
}
fn fill_status_cache_slot(
status_cache: &mut BankStatusCache,
blockhash: &Hash,
slot: u64,
num_txs: usize,
) {
for _ in 0..num_txs {
let tx_hash = Hash::new_unique();
status_cache.insert(blockhash, tx_hash, slot, Ok(()));
}
}
#[bench]
fn bench_status_cache_check_and_insert(bencher: &mut Bencher) {
let max_cache_entries = MAX_CACHE_ENTRIES as u64;
let mut status_cache = BankStatusCache::default();
fill_status_cache(&mut status_cache, max_cache_entries - 1, 100_000);
let blockhash = Hash::new_unique();
fill_status_cache_slot(&mut status_cache, &blockhash, max_cache_entries, 100_000);
let slot = max_cache_entries + 1;
let ancestors = Ancestors::from((slot - 32..slot).collect::<Vec<u64>>());
let batch_size = 1_000;
let mut tx_hashes = Vec::with_capacity(batch_size);
let mut rng = SmallRng::seed_from_u64(0);
for _ in 0..batch_size {
let mut sigbytes = [0u8; SIGNATURE_BYTES];
rng.fill(&mut sigbytes);
tx_hashes.push(Signature::from(sigbytes));
}
bencher.iter(|| {
for tx_hash in &tx_hashes {
if status_cache
.get_status(*tx_hash, &blockhash, &ancestors)
.is_none()
{
status_cache.insert(&blockhash, *tx_hash, slot, Ok(()));
}
}
});
}
#[bench]
fn bench_status_cache_add_roots(bencher: &mut Bencher) {
let max_cache_entries = MAX_CACHE_ENTRIES as u64;
let mut status_cache = BankStatusCache::default();
fill_status_cache(&mut status_cache, max_cache_entries, 100_000);
let start_slot = max_cache_entries + 1;
bencher.iter(|| {
for root in start_slot..start_slot + max_cache_entries {
status_cache.add_root(root);
}
});
}