From 27de30675b7202e20da9b9f87b3825c5c916b1ce Mon Sep 17 00:00:00 2001 From: behzad nouri Date: Thu, 23 Jan 2025 10:59:21 -0600 Subject: [PATCH 1/2] adds benchmark for shred::merkle::make_shreds_from_data --- ledger/Cargo.toml | 3 + ledger/benches/make_shreds_from_entries.rs | 149 +++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 ledger/benches/make_shreds_from_entries.rs diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 72a2e9a43fe12c..755448512fe38b 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -116,6 +116,9 @@ name = "sigverify_shreds" [[bench]] name = "blockstore" +[[bench]] +name = "make_shreds_from_entries" + [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/ledger/benches/make_shreds_from_entries.rs b/ledger/benches/make_shreds_from_entries.rs new file mode 100644 index 00000000000000..4f2c11659cd999 --- /dev/null +++ b/ledger/benches/make_shreds_from_entries.rs @@ -0,0 +1,149 @@ +#![feature(test)] +#![allow(clippy::arithmetic_side_effects)] +extern crate test; +use { + rand::Rng, + solana_entry::entry::Entry, + solana_ledger::shred::{ProcessShredsStats, ReedSolomonCache, Shred, Shredder}, + solana_sdk::{ + hash::Hash, packet::PACKET_DATA_SIZE, pubkey::Pubkey, signer::keypair::Keypair, + transaction::Transaction, + }, + std::iter::repeat_with, + test::Bencher, +}; + +fn make_dummy_hash(rng: &mut R) -> Hash { + Hash::from(rng.gen::<[u8; 32]>()) +} + +fn make_dummy_transaction(rng: &mut R) -> Transaction { + solana_sdk::system_transaction::transfer( + &Keypair::new(), // from + &Pubkey::from(rng.gen::<[u8; 32]>()), // to + rng.gen(), // lamports + make_dummy_hash(rng), // recent_blockhash + ) +} + +fn make_dummy_entry(rng: &mut R) -> Entry { + let count = rng.gen_range(1..20); + let transactions = repeat_with(|| make_dummy_transaction(rng)) + .take(count) + .collect(); + Entry::new( + &make_dummy_hash(rng), // prev_hash + 1, // num_hashes + transactions, + ) +} + +fn make_dummy_entries(rng: &mut R, data_size: usize) -> Vec { + let mut serialized_size = 8; // length prefix. + repeat_with(|| make_dummy_entry(rng)) + .take_while(|entry| { + serialized_size += bincode::serialized_size(entry).unwrap(); + serialized_size < data_size as u64 + }) + .collect() +} + +fn make_shreds_from_entries( + rng: &mut R, + shredder: &Shredder, + keypair: &Keypair, + entries: &[Entry], + is_last_in_slot: bool, + chained_merkle_root: Option, + reed_solomon_cache: &ReedSolomonCache, + stats: &mut ProcessShredsStats, +) -> (Vec, Vec) { + let (data, code) = shredder.entries_to_shreds( + keypair, + entries, + is_last_in_slot, + chained_merkle_root, + rng.gen_range(0..2_000), // next_shred_index + rng.gen_range(0..2_000), // next_code_index + true, // merkle_variant + reed_solomon_cache, + stats, + ); + (std::hint::black_box(data), std::hint::black_box(code)) +} + +fn run_make_shreds_from_entries(bencher: &mut Bencher, data_size: usize, is_last_in_slot: bool) { + let mut rng = rand::thread_rng(); + let slot = 315_892_061 + rng.gen_range(0..=100_000); + let parent_offset = rng.gen_range(1..=u16::MAX); + let shredder = Shredder::new( + slot, + slot - u64::from(parent_offset), // parent_slot + rng.gen_range(0..64), // reference_tick + rng.gen(), // shred_version + ) + .unwrap(); + let keypair = Keypair::new(); + let entries = make_dummy_entries(&mut rng, data_size); + let chained_merkle_root = Some(make_dummy_hash(&mut rng)); + let reed_solomon_cache = ReedSolomonCache::default(); + let mut stats = ProcessShredsStats::default(); + // Initialize the thread-pool and warm the Reed-Solomon cache. + for _ in 0..10 { + make_shreds_from_entries( + &mut rng, + &shredder, + &keypair, + &entries, + is_last_in_slot, + chained_merkle_root, + &reed_solomon_cache, + &mut stats, + ); + } + bencher.iter(|| { + let (data, code) = make_shreds_from_entries( + &mut rng, + &shredder, + &keypair, + &entries, + is_last_in_slot, + chained_merkle_root, + &reed_solomon_cache, + &mut stats, + ); + std::hint::black_box(data); + std::hint::black_box(code); + }); +} + +macro_rules! make_bench { + ($name:ident, $size:literal, $last:literal) => { + #[bench] + fn $name(bencher: &mut Bencher) { + run_make_shreds_from_entries( + bencher, + $size * PACKET_DATA_SIZE, // data_size + $last, // is_last_in_slot + ); + } + }; +} + +make_bench!(bench_make_shreds_from_entries_016, 16, false); +make_bench!(bench_make_shreds_from_entries_024, 24, false); +make_bench!(bench_make_shreds_from_entries_032, 32, false); +make_bench!(bench_make_shreds_from_entries_048, 48, false); +make_bench!(bench_make_shreds_from_entries_064, 64, false); +make_bench!(bench_make_shreds_from_entries_096, 96, false); +make_bench!(bench_make_shreds_from_entries_128, 128, false); +make_bench!(bench_make_shreds_from_entries_256, 256, false); + +make_bench!(bench_make_shreds_from_entries_last_016, 16, true); +make_bench!(bench_make_shreds_from_entries_last_024, 24, true); +make_bench!(bench_make_shreds_from_entries_last_032, 32, true); +make_bench!(bench_make_shreds_from_entries_last_048, 48, true); +make_bench!(bench_make_shreds_from_entries_last_064, 64, true); +make_bench!(bench_make_shreds_from_entries_last_096, 96, true); +make_bench!(bench_make_shreds_from_entries_last_128, 128, true); +make_bench!(bench_make_shreds_from_entries_last_256, 256, true); From b8c2ff9b876e0143989c1299c28af57bd8a72410 Mon Sep 17 00:00:00 2001 From: behzad nouri Date: Fri, 24 Jan 2025 08:25:23 -0600 Subject: [PATCH 2/2] switches to criterion --- Cargo.lock | 1 + ledger/Cargo.toml | 2 + ledger/benches/make_shreds_from_entries.rs | 79 ++++++++++------------ 3 files changed, 38 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a903314586e2d9..496dde55bec241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7964,6 +7964,7 @@ dependencies = [ "bzip2", "chrono", "chrono-humanize", + "criterion", "crossbeam-channel", "dashmap", "eager", diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 755448512fe38b..836a81fc75b29d 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -92,6 +92,7 @@ features = ["lz4"] [dev-dependencies] bs58 = { workspace = true } +criterion = { workspace = true } solana-account-decoder = { workspace = true } solana-logger = { workspace = true } solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } @@ -118,6 +119,7 @@ name = "blockstore" [[bench]] name = "make_shreds_from_entries" +harness = false [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/ledger/benches/make_shreds_from_entries.rs b/ledger/benches/make_shreds_from_entries.rs index 4f2c11659cd999..a7fa9ee7ae30fc 100644 --- a/ledger/benches/make_shreds_from_entries.rs +++ b/ledger/benches/make_shreds_from_entries.rs @@ -1,7 +1,6 @@ -#![feature(test)] #![allow(clippy::arithmetic_side_effects)] -extern crate test; use { + criterion::{black_box, criterion_group, criterion_main, Criterion}, rand::Rng, solana_entry::entry::Entry, solana_ledger::shred::{ProcessShredsStats, ReedSolomonCache, Shred, Shredder}, @@ -10,7 +9,6 @@ use { transaction::Transaction, }, std::iter::repeat_with, - test::Bencher, }; fn make_dummy_hash(rng: &mut R) -> Hash { @@ -69,10 +67,15 @@ fn make_shreds_from_entries( reed_solomon_cache, stats, ); - (std::hint::black_box(data), std::hint::black_box(code)) + (black_box(data), black_box(code)) } -fn run_make_shreds_from_entries(bencher: &mut Bencher, data_size: usize, is_last_in_slot: bool) { +fn run_make_shreds_from_entries( + name: &str, + c: &mut Criterion, + num_packets: usize, + is_last_in_slot: bool, +) { let mut rng = rand::thread_rng(); let slot = 315_892_061 + rng.gen_range(0..=100_000); let parent_offset = rng.gen_range(1..=u16::MAX); @@ -84,6 +87,7 @@ fn run_make_shreds_from_entries(bencher: &mut Bencher, data_size: usize, is_last ) .unwrap(); let keypair = Keypair::new(); + let data_size = num_packets * PACKET_DATA_SIZE; let entries = make_dummy_entries(&mut rng, data_size); let chained_merkle_root = Some(make_dummy_hash(&mut rng)); let reed_solomon_cache = ReedSolomonCache::default(); @@ -101,49 +105,36 @@ fn run_make_shreds_from_entries(bencher: &mut Bencher, data_size: usize, is_last &mut stats, ); } - bencher.iter(|| { - let (data, code) = make_shreds_from_entries( - &mut rng, - &shredder, - &keypair, - &entries, - is_last_in_slot, - chained_merkle_root, - &reed_solomon_cache, - &mut stats, - ); - std::hint::black_box(data); - std::hint::black_box(code); + c.bench_function(name, |b| { + b.iter(|| { + let (data, code) = make_shreds_from_entries( + &mut rng, + &shredder, + &keypair, + &entries, + is_last_in_slot, + chained_merkle_root, + &reed_solomon_cache, + &mut stats, + ); + black_box(data); + black_box(code); + }) }); } -macro_rules! make_bench { - ($name:ident, $size:literal, $last:literal) => { - #[bench] - fn $name(bencher: &mut Bencher) { - run_make_shreds_from_entries( - bencher, - $size * PACKET_DATA_SIZE, // data_size - $last, // is_last_in_slot +fn bench_make_shreds_from_entries(c: &mut Criterion) { + for is_last_in_slot in [false, true] { + for num_packets in [16, 20, 24, 28, 32, 48, 64, 96, 128, 256] { + let name = format!( + "bench_make_shreds_from_entries_{}{}", + if is_last_in_slot { "last_" } else { "" }, + num_packets ); + run_make_shreds_from_entries(&name, c, num_packets, is_last_in_slot); } - }; + } } -make_bench!(bench_make_shreds_from_entries_016, 16, false); -make_bench!(bench_make_shreds_from_entries_024, 24, false); -make_bench!(bench_make_shreds_from_entries_032, 32, false); -make_bench!(bench_make_shreds_from_entries_048, 48, false); -make_bench!(bench_make_shreds_from_entries_064, 64, false); -make_bench!(bench_make_shreds_from_entries_096, 96, false); -make_bench!(bench_make_shreds_from_entries_128, 128, false); -make_bench!(bench_make_shreds_from_entries_256, 256, false); - -make_bench!(bench_make_shreds_from_entries_last_016, 16, true); -make_bench!(bench_make_shreds_from_entries_last_024, 24, true); -make_bench!(bench_make_shreds_from_entries_last_032, 32, true); -make_bench!(bench_make_shreds_from_entries_last_048, 48, true); -make_bench!(bench_make_shreds_from_entries_last_064, 64, true); -make_bench!(bench_make_shreds_from_entries_last_096, 96, true); -make_bench!(bench_make_shreds_from_entries_last_128, 128, true); -make_bench!(bench_make_shreds_from_entries_last_256, 256, true); +criterion_group!(benches, bench_make_shreds_from_entries,); +criterion_main!(benches);