diff --git a/benches/bank.rs b/benches/bank.rs new file mode 100644 index 0000000000..c650e414aa --- /dev/null +++ b/benches/bank.rs @@ -0,0 +1,51 @@ +#![feature(test)] + +extern crate bincode; +extern crate rayon; +extern crate solana; +extern crate test; + +use bincode::serialize; +use rayon::prelude::*; +use solana::bank::*; +use solana::hash::hash; +use solana::mint::Mint; +use solana::signature::{KeyPair, KeyPairUtil}; +use solana::transaction::Transaction; +use test::Bencher; + +#[bench] +fn bench_process_transaction(bencher: &mut Bencher) { + let mint = Mint::new(100_000_000); + let bank = Bank::new(&mint); + + // Create transactions between unrelated parties. + let transactions: Vec<_> = (0..4096) + .into_par_iter() + .map(|i| { + // Seed the 'from' account. + let rando0 = KeyPair::new(); + let tx = Transaction::new(&mint.keypair(), rando0.pubkey(), 10_000, mint.last_id()); + assert!(bank.process_transaction(&tx).is_ok()); + + // Seed the 'to' account and a cell for its signature. + let last_id = hash(&serialize(&i).unwrap()); // Unique hash + bank.register_entry_id(&last_id); + + let rando1 = KeyPair::new(); + let tx = Transaction::new(&rando0, rando1.pubkey(), 1, last_id); + assert!(bank.process_transaction(&tx.clone()).is_ok()); + + // Finally, return a the transaction to benchmark. + tx + }) + .collect(); + + bencher.iter(|| { + // Since benchmarker runs this multiple times, we need to clear the signatures. + bank.clear_signatures(); + + let results = bank.process_transactions(transactions.clone()); + assert!(results.iter().all(Result::is_ok)); + }); +} diff --git a/src/bank.rs b/src/bank.rs index a882f199fb..73cbcc37c6 100644 --- a/src/bank.rs +++ b/src/bank.rs @@ -162,6 +162,13 @@ impl Bank { } } + /// Forget all signatures. Useful for benchmarking. + pub fn clear_signatures(&self) { + for (_, sigs) in self.last_ids_sigs.write().unwrap().iter_mut() { + sigs.clear(); + } + } + fn reserve_signature_with_last_id(&self, signature: &Signature, last_id: &Hash) -> Result<()> { if let Some(entry) = self.last_ids_sigs .write() @@ -258,7 +265,7 @@ impl Bank { /// Process a Transaction. If it contains a payment plan that requires a witness /// to progress, the payment plan will be stored in the bank. - fn process_transaction(&self, tx: &Transaction) -> Result<()> { + pub fn process_transaction(&self, tx: &Transaction) -> Result<()> { let bals = &mut self.balances.write().unwrap(); self.apply_debits(tx, bals)?; self.apply_credits(tx, bals); @@ -822,53 +829,3 @@ mod tests { assert_eq!(bank.get_balance(&mint.pubkey()), 1); } } - -#[cfg(all(feature = "unstable", test))] -mod bench { - extern crate test; - use self::test::Bencher; - use bank::*; - use bincode::serialize; - use hash::hash; - use rayon::prelude::*; - use signature::KeyPairUtil; - - #[bench] - fn bench_process_transaction(bencher: &mut Bencher) { - let mint = Mint::new(100_000_000); - let bank = Bank::new(&mint); - // Create transactions between unrelated parties. - let transactions: Vec<_> = (0..4096) - .into_par_iter() - .map(|i| { - // Seed the 'from' account. - let rando0 = KeyPair::new(); - let tx = Transaction::new(&mint.keypair(), rando0.pubkey(), 1_000, mint.last_id()); - bank.process_transaction(&tx).unwrap(); - - // Seed the 'to' account and a cell for its signature. - let last_id = hash(&serialize(&i).unwrap()); // Unique hash - bank.register_entry_id(&last_id); - - let rando1 = KeyPair::new(); - let tx = Transaction::new(&rando0, rando1.pubkey(), 1, last_id); - bank.process_transaction(&tx).unwrap(); - - // Finally, return a transaction that's unique - Transaction::new(&rando0, rando1.pubkey(), 1, last_id) - }) - .collect(); - bencher.iter(|| { - // Since benchmarker runs this multiple times, we need to clear the signatures. - for (_, sigs) in bank.last_ids_sigs.write().unwrap().iter_mut() { - sigs.clear(); - } - - assert!( - bank.process_transactions(transactions.clone()) - .iter() - .all(|x| x.is_ok()) - ); - }); - } -}