Merge pull request #230 from garious/generalize-topackets
Benchmark the banking stage
This commit is contained in:
@ -251,3 +251,58 @@ impl BankingStage {
|
|||||||
// println!("{} tps", tps);
|
// println!("{} tps", tps);
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "unstable", test))]
|
||||||
|
mod bench {
|
||||||
|
extern crate test;
|
||||||
|
use self::test::Bencher;
|
||||||
|
use bank::*;
|
||||||
|
use banking_stage::BankingStage;
|
||||||
|
use event::Event;
|
||||||
|
use mint::Mint;
|
||||||
|
use packet::{to_packets, PacketRecycler};
|
||||||
|
use recorder::Signal;
|
||||||
|
use signature::{KeyPair, KeyPairUtil};
|
||||||
|
use std::iter;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn stage_bench(bencher: &mut Bencher) {
|
||||||
|
let tx = 100_usize;
|
||||||
|
let mint = Mint::new(1_000_000_000);
|
||||||
|
let pubkey = KeyPair::new().pubkey();
|
||||||
|
|
||||||
|
let events: Vec<_> = (0..tx)
|
||||||
|
.map(|i| Event::new_transaction(&mint.keypair(), pubkey, i as i64, mint.last_id()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let (verified_sender, verified_receiver) = channel();
|
||||||
|
let (signal_sender, signal_receiver) = channel();
|
||||||
|
let packet_recycler = PacketRecycler::default();
|
||||||
|
let verified: Vec<_> = to_packets(&packet_recycler, events)
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| {
|
||||||
|
let len = (*x).read().unwrap().packets.len();
|
||||||
|
(x, iter::repeat(1).take(len).collect())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
bencher.iter(move || {
|
||||||
|
let bank = Arc::new(Bank::new(&mint));
|
||||||
|
verified_sender.send(verified.clone()).unwrap();
|
||||||
|
BankingStage::process_packets(
|
||||||
|
bank.clone(),
|
||||||
|
&verified_receiver,
|
||||||
|
&signal_sender,
|
||||||
|
&packet_recycler,
|
||||||
|
).unwrap();
|
||||||
|
let signal = signal_receiver.recv().unwrap();
|
||||||
|
if let Signal::Events(ref events) = signal {
|
||||||
|
assert_eq!(events.len(), tx);
|
||||||
|
} else {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,7 +8,7 @@ extern crate untrusted;
|
|||||||
use isatty::stdin_isatty;
|
use isatty::stdin_isatty;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use solana::bank::MAX_ENTRY_IDS;
|
use solana::bank::MAX_ENTRY_IDS;
|
||||||
use solana::entry::{create_entry, next_entry};
|
use solana::entry::{next_entry, Entry};
|
||||||
use solana::event::Event;
|
use solana::event::Event;
|
||||||
use solana::mint::MintDemo;
|
use solana::mint::MintDemo;
|
||||||
use solana::signature::{GenKeys, KeyPair, KeyPairUtil};
|
use solana::signature::{GenKeys, KeyPair, KeyPairUtil};
|
||||||
@ -61,7 +61,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("Logging the creation of {} accounts...", num_accounts);
|
eprintln!("Logging the creation of {} accounts...", num_accounts);
|
||||||
let entry = create_entry(&last_id, 0, events);
|
let entry = Entry::new(&last_id, 0, events);
|
||||||
println!("{}", serde_json::to_string(&entry).unwrap());
|
println!("{}", serde_json::to_string(&entry).unwrap());
|
||||||
|
|
||||||
eprintln!("Creating {} empty entries...", MAX_ENTRY_IDS);
|
eprintln!("Creating {} empty entries...", MAX_ENTRY_IDS);
|
||||||
|
49
src/entry.rs
49
src/entry.rs
@ -25,6 +25,25 @@ pub struct Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
|
/// Creates the next Entry `num_hashes` after `start_hash`.
|
||||||
|
pub fn new(start_hash: &Hash, cur_hashes: u64, events: Vec<Event>) -> Self {
|
||||||
|
let num_hashes = cur_hashes + if events.is_empty() { 0 } else { 1 };
|
||||||
|
let id = next_hash(start_hash, 0, &events);
|
||||||
|
Entry {
|
||||||
|
num_hashes,
|
||||||
|
id,
|
||||||
|
events,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates the next Tick Entry `num_hashes` after `start_hash`.
|
||||||
|
pub fn new_mut(start_hash: &mut Hash, cur_hashes: &mut u64, events: Vec<Event>) -> Self {
|
||||||
|
let entry = Self::new(start_hash, *cur_hashes, events);
|
||||||
|
*start_hash = entry.id;
|
||||||
|
*cur_hashes = 0;
|
||||||
|
entry
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a Entry from the number of hashes `num_hashes` since the previous event
|
/// Creates a Entry from the number of hashes `num_hashes` since the previous event
|
||||||
/// and that resulting `id`.
|
/// and that resulting `id`.
|
||||||
pub fn new_tick(num_hashes: u64, id: &Hash) -> Self {
|
pub fn new_tick(num_hashes: u64, id: &Hash) -> Self {
|
||||||
@ -84,25 +103,6 @@ pub fn next_hash(start_hash: &Hash, num_hashes: u64, events: &[Event]) -> Hash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the next Entry `num_hashes` after `start_hash`.
|
|
||||||
pub fn create_entry(start_hash: &Hash, cur_hashes: u64, events: Vec<Event>) -> Entry {
|
|
||||||
let num_hashes = cur_hashes + if events.is_empty() { 0 } else { 1 };
|
|
||||||
let id = next_hash(start_hash, 0, &events);
|
|
||||||
Entry {
|
|
||||||
num_hashes,
|
|
||||||
id,
|
|
||||||
events,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates the next Tick Entry `num_hashes` after `start_hash`.
|
|
||||||
pub fn create_entry_mut(start_hash: &mut Hash, cur_hashes: &mut u64, events: Vec<Event>) -> Entry {
|
|
||||||
let entry = create_entry(start_hash, *cur_hashes, events);
|
|
||||||
*start_hash = entry.id;
|
|
||||||
*cur_hashes = 0;
|
|
||||||
entry
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates the next Tick or Event Entry `num_hashes` after `start_hash`.
|
/// Creates the next Tick or Event Entry `num_hashes` after `start_hash`.
|
||||||
pub fn next_entry(start_hash: &Hash, num_hashes: u64, events: Vec<Event>) -> Entry {
|
pub fn next_entry(start_hash: &Hash, num_hashes: u64, events: Vec<Event>) -> Entry {
|
||||||
Entry {
|
Entry {
|
||||||
@ -116,11 +116,10 @@ pub fn next_entry(start_hash: &Hash, num_hashes: u64, events: Vec<Event>) -> Ent
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use entry::create_entry;
|
use entry::Entry;
|
||||||
use event::Event;
|
use event::Event;
|
||||||
use hash::hash;
|
use hash::hash;
|
||||||
use signature::{KeyPair, KeyPairUtil};
|
use signature::{KeyPair, KeyPairUtil};
|
||||||
use transaction::Transaction;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_entry_verify() {
|
fn test_entry_verify() {
|
||||||
@ -138,9 +137,9 @@ mod tests {
|
|||||||
|
|
||||||
// First, verify entries
|
// First, verify entries
|
||||||
let keypair = KeyPair::new();
|
let keypair = KeyPair::new();
|
||||||
let tr0 = Event::Transaction(Transaction::new(&keypair, keypair.pubkey(), 0, zero));
|
let tr0 = Event::new_transaction(&keypair, keypair.pubkey(), 0, zero);
|
||||||
let tr1 = Event::Transaction(Transaction::new(&keypair, keypair.pubkey(), 1, zero));
|
let tr1 = Event::new_transaction(&keypair, keypair.pubkey(), 1, zero);
|
||||||
let mut e0 = create_entry(&zero, 0, vec![tr0.clone(), tr1.clone()]);
|
let mut e0 = Entry::new(&zero, 0, vec![tr0.clone(), tr1.clone()]);
|
||||||
assert!(e0.verify(&zero));
|
assert!(e0.verify(&zero));
|
||||||
|
|
||||||
// Next, swap two events and ensure verification fails.
|
// Next, swap two events and ensure verification fails.
|
||||||
@ -157,7 +156,7 @@ mod tests {
|
|||||||
let keypair = KeyPair::new();
|
let keypair = KeyPair::new();
|
||||||
let tr0 = Event::new_timestamp(&keypair, Utc::now());
|
let tr0 = Event::new_timestamp(&keypair, Utc::now());
|
||||||
let tr1 = Event::new_signature(&keypair, Default::default());
|
let tr1 = Event::new_signature(&keypair, Default::default());
|
||||||
let mut e0 = create_entry(&zero, 0, vec![tr0.clone(), tr1.clone()]);
|
let mut e0 = Entry::new(&zero, 0, vec![tr0.clone(), tr1.clone()]);
|
||||||
assert!(e0.verify(&zero));
|
assert!(e0.verify(&zero));
|
||||||
|
|
||||||
// Next, swap two witness events and ensure verification fails.
|
// Next, swap two witness events and ensure verification fails.
|
||||||
|
11
src/event.rs
11
src/event.rs
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
|
use hash::Hash;
|
||||||
use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil};
|
use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil};
|
||||||
use transaction::Transaction;
|
use transaction::Transaction;
|
||||||
|
|
||||||
@ -22,6 +23,16 @@ pub enum Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Event {
|
impl Event {
|
||||||
|
pub fn new_transaction(
|
||||||
|
from_keypair: &KeyPair,
|
||||||
|
to: PublicKey,
|
||||||
|
tokens: i64,
|
||||||
|
last_id: Hash,
|
||||||
|
) -> Self {
|
||||||
|
let tr = Transaction::new(from_keypair, to, tokens, last_id);
|
||||||
|
Event::Transaction(tr)
|
||||||
|
}
|
||||||
|
|
||||||
/// Create and sign a new Witness Timestamp. Used for unit-testing.
|
/// Create and sign a new Witness Timestamp. Used for unit-testing.
|
||||||
pub fn new_timestamp(from: &KeyPair, dt: DateTime<Utc>) -> Self {
|
pub fn new_timestamp(from: &KeyPair, dt: DateTime<Utc>) -> Self {
|
||||||
let sign_data = serialize(&dt).expect("serialize 'dt' in pub fn new_timestamp");
|
let sign_data = serialize(&dt).expect("serialize 'dt' in pub fn new_timestamp");
|
||||||
|
@ -123,7 +123,6 @@ pub fn reconstruct_entries_from_blobs(blobs: &VecDeque<SharedBlob>) -> Vec<Entry
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use entry;
|
|
||||||
use hash::hash;
|
use hash::hash;
|
||||||
use packet::BlobRecycler;
|
use packet::BlobRecycler;
|
||||||
use signature::{KeyPair, KeyPairUtil};
|
use signature::{KeyPair, KeyPairUtil};
|
||||||
@ -150,7 +149,7 @@ mod tests {
|
|||||||
let keypair = KeyPair::new();
|
let keypair = KeyPair::new();
|
||||||
let tr0 = Event::Transaction(Transaction::new(&keypair, keypair.pubkey(), 1, one));
|
let tr0 = Event::Transaction(Transaction::new(&keypair, keypair.pubkey(), 1, one));
|
||||||
let events = vec![tr0.clone(); 10000];
|
let events = vec![tr0.clone(); 10000];
|
||||||
let e0 = entry::create_entry(&zero, 0, events);
|
let e0 = Entry::new(&zero, 0, events);
|
||||||
|
|
||||||
let entry_list = vec![e0.clone(); 1];
|
let entry_list = vec![e0.clone(); 1];
|
||||||
let blob_recycler = BlobRecycler::default();
|
let blob_recycler = BlobRecycler::default();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
//! The `mint` module is a library for generating the chain's genesis block.
|
//! The `mint` module is a library for generating the chain's genesis block.
|
||||||
|
|
||||||
use entry::Entry;
|
use entry::Entry;
|
||||||
use entry::create_entry;
|
|
||||||
use event::Event;
|
use event::Event;
|
||||||
use hash::{hash, Hash};
|
use hash::{hash, Hash};
|
||||||
use ring::rand::SystemRandom;
|
use ring::rand::SystemRandom;
|
||||||
@ -55,8 +54,8 @@ impl Mint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_entries(&self) -> Vec<Entry> {
|
pub fn create_entries(&self) -> Vec<Entry> {
|
||||||
let e0 = create_entry(&self.seed(), 0, vec![]);
|
let e0 = Entry::new(&self.seed(), 0, vec![]);
|
||||||
let e1 = create_entry(&e0.id, 0, self.create_events());
|
let e1 = Entry::new(&e0.id, 0, self.create_events());
|
||||||
vec![e0, e1]
|
vec![e0, e1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
//! Event, the latest hash, and the number of hashes since the last event.
|
//! Event, the latest hash, and the number of hashes since the last event.
|
||||||
//! The resulting stream of entries represents ordered events in time.
|
//! The resulting stream of entries represents ordered events in time.
|
||||||
|
|
||||||
use entry::{create_entry_mut, Entry};
|
use entry::Entry;
|
||||||
use event::Event;
|
use event::Event;
|
||||||
use hash::{hash, Hash};
|
use hash::{hash, Hash};
|
||||||
use std::sync::mpsc::{Receiver, Sender, TryRecvError};
|
use std::sync::mpsc::{Receiver, Sender, TryRecvError};
|
||||||
@ -48,7 +48,7 @@ impl Recorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_entry(&mut self, events: Vec<Event>) -> Result<(), ExitReason> {
|
pub fn record_entry(&mut self, events: Vec<Event>) -> Result<(), ExitReason> {
|
||||||
let entry = create_entry_mut(&mut self.last_hash, &mut self.num_hashes, events);
|
let entry = Entry::new_mut(&mut self.last_hash, &mut self.num_hashes, events);
|
||||||
self.sender
|
self.sender
|
||||||
.send(entry)
|
.send(entry)
|
||||||
.or(Err(ExitReason::SendDisconnected))?;
|
.or(Err(ExitReason::SendDisconnected))?;
|
||||||
@ -89,7 +89,6 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use signature::{KeyPair, KeyPairUtil};
|
use signature::{KeyPair, KeyPairUtil};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use transaction::Transaction;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_events() {
|
fn test_events() {
|
||||||
@ -99,8 +98,8 @@ mod tests {
|
|||||||
let mut recorder = Recorder::new(signal_receiver, entry_sender, zero);
|
let mut recorder = Recorder::new(signal_receiver, entry_sender, zero);
|
||||||
let alice_keypair = KeyPair::new();
|
let alice_keypair = KeyPair::new();
|
||||||
let bob_pubkey = KeyPair::new().pubkey();
|
let bob_pubkey = KeyPair::new().pubkey();
|
||||||
let event0 = Event::Transaction(Transaction::new(&alice_keypair, bob_pubkey, 1, zero));
|
let event0 = Event::new_transaction(&alice_keypair, bob_pubkey, 1, zero);
|
||||||
let event1 = Event::Transaction(Transaction::new(&alice_keypair, bob_pubkey, 2, zero));
|
let event1 = Event::new_transaction(&alice_keypair, bob_pubkey, 2, zero);
|
||||||
signal_sender
|
signal_sender
|
||||||
.send(Signal::Events(vec![event0, event1]))
|
.send(Signal::Events(vec![event0, event1]))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
10
src/tvu.rs
10
src/tvu.rs
@ -218,7 +218,7 @@ mod tests {
|
|||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use crdt::Crdt;
|
use crdt::Crdt;
|
||||||
use entry;
|
use entry::Entry;
|
||||||
use event::Event;
|
use event::Event;
|
||||||
use hash::{hash, Hash};
|
use hash::{hash, Hash};
|
||||||
use logger;
|
use logger;
|
||||||
@ -231,7 +231,6 @@ mod tests {
|
|||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use streamer;
|
use streamer;
|
||||||
use transaction::Transaction;
|
|
||||||
use tvu::{test_node, Tvu};
|
use tvu::{test_node, Tvu};
|
||||||
|
|
||||||
/// Test that mesasge sent from leader to target1 and repliated to target2
|
/// Test that mesasge sent from leader to target1 and repliated to target2
|
||||||
@ -320,11 +319,11 @@ mod tests {
|
|||||||
let bank = &tvu.bank;
|
let bank = &tvu.bank;
|
||||||
|
|
||||||
let tr0 = Event::new_timestamp(&bob_keypair, Utc::now());
|
let tr0 = Event::new_timestamp(&bob_keypair, Utc::now());
|
||||||
let entry0 = entry::create_entry(&cur_hash, i, vec![tr0]);
|
let entry0 = Entry::new(&cur_hash, i, vec![tr0]);
|
||||||
bank.register_entry_id(&cur_hash);
|
bank.register_entry_id(&cur_hash);
|
||||||
cur_hash = hash(&cur_hash);
|
cur_hash = hash(&cur_hash);
|
||||||
|
|
||||||
let tr1 = Transaction::new(
|
let tr1 = Event::new_transaction(
|
||||||
&mint.keypair(),
|
&mint.keypair(),
|
||||||
bob_keypair.pubkey(),
|
bob_keypair.pubkey(),
|
||||||
transfer_amount,
|
transfer_amount,
|
||||||
@ -332,8 +331,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
bank.register_entry_id(&cur_hash);
|
bank.register_entry_id(&cur_hash);
|
||||||
cur_hash = hash(&cur_hash);
|
cur_hash = hash(&cur_hash);
|
||||||
let entry1 =
|
let entry1 = Entry::new(&cur_hash, i + num_blobs, vec![tr1]);
|
||||||
entry::create_entry(&cur_hash, i + num_blobs, vec![Event::Transaction(tr1)]);
|
|
||||||
bank.register_entry_id(&cur_hash);
|
bank.register_entry_id(&cur_hash);
|
||||||
cur_hash = hash(&cur_hash);
|
cur_hash = hash(&cur_hash);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user