// This bench attempts to justify the value of `solana_core::poh_service::NUM_HASHES_PER_BATCH` #![feature(test)] extern crate test; use solana_core::poh_service::NUM_HASHES_PER_BATCH; use solana_ledger::poh::Poh; use solana_sdk::hash::Hash; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use test::Bencher; const NUM_HASHES: u64 = 30_000; // Should require ~10ms on a 2017 MacBook Pro #[bench] // No locking. Fastest. fn bench_poh_hash(bencher: &mut Bencher) { let mut poh = Poh::new(Hash::default(), None); bencher.iter(|| { poh.hash(NUM_HASHES); }) } #[bench] // Lock on each iteration. Slowest. fn bench_arc_mutex_poh_hash(bencher: &mut Bencher) { let poh = Arc::new(Mutex::new(Poh::new(Hash::default(), None))); bencher.iter(|| { for _ in 0..NUM_HASHES { poh.lock().unwrap().hash(1); } }) } #[bench] // Acquire lock every NUM_HASHES_PER_BATCH iterations. // Speed should be close to bench_poh_hash() if NUM_HASHES_PER_BATCH is set well. fn bench_arc_mutex_poh_batched_hash(bencher: &mut Bencher) { let poh = Arc::new(Mutex::new(Poh::new(Hash::default(), Some(NUM_HASHES)))); //let exit = Arc::new(AtomicBool::new(false)); let exit = Arc::new(AtomicBool::new(true)); bencher.iter(|| { // NOTE: This block attempts to look as close as possible to `PohService::tick_producer()` loop { if poh.lock().unwrap().hash(NUM_HASHES_PER_BATCH) { poh.lock().unwrap().tick().unwrap(); if exit.load(Ordering::Relaxed) { break; } } } }) } #[bench] // Worst case transaction record delay due to batch hashing at NUM_HASHES_PER_BATCH fn bench_poh_lock_time_per_batch(bencher: &mut Bencher) { let mut poh = Poh::new(Hash::default(), None); bencher.iter(|| { poh.hash(NUM_HASHES_PER_BATCH); }) }