forked from aptos-labs/aptos-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[benchmark] RuBen: Transaction throughput benchmark tool.
* Enhance `Benchmarker` * Naive one-client approach seems bottlenecked by the single client's request sending throughput. With multiple parallel AC clients, each sending async requests, requesting 2256 txns is reduced from approx 4 seconds to 1.6 sec with 4 AC clients. * Load faucet account and sync its sequence number with validator before minting. * Only holds a wallet, instead of client_proxy or grpc_client. * It has 2 built-in TXN generation approaches: ring transactions and pairwise transactions. In future, we need to separate TXN generation out into another module. * Create `RuBen` * A driver that runs benchmarker with pre-generated txns requests and estimate TX throughput. * RuBen connects to existing `libra_swarm` by parsing command line arguments (e.g. num_clients and validator_addresses). To run RuBen locally, just passing both `faucet_keypair_path` and `swarm_config_dir` (from running `libra_swarm`) is enough (other arguments will use their default value): * See `ruben --help` for full arguments.
- Loading branch information
1 parent
779ebbe
commit 1ad6ac4
Showing
7 changed files
with
657 additions
and
186 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
use admission_control_proto::proto::admission_control_grpc::AdmissionControlClient; | ||
use benchmark::{ | ||
ruben_opt::{Executable, Opt}, | ||
Benchmarker, | ||
}; | ||
use client::AccountData; | ||
use debug_interface::NodeDebugClient; | ||
use grpcio::{ChannelBuilder, EnvBuilder}; | ||
use logger::{self, prelude::*}; | ||
use std::sync::Arc; | ||
|
||
/// Simply submit some TXNs to test the liveness of the network. Here we use ring TXN pattern | ||
/// to generate request, which scales linear with the number of accounts. | ||
/// In one epoch, we play the sequence of ring TXN requests repeatedly for num_rounds times. | ||
fn test_liveness( | ||
bm: &mut Benchmarker, | ||
accounts: &mut [AccountData], | ||
num_rounds: u64, | ||
num_epochs: u64, | ||
) { | ||
for _ in 0..num_epochs { | ||
let mut repeated_tx_reqs = vec![]; | ||
for _ in 0..num_rounds { | ||
let tx_reqs = bm.gen_ring_txn_requests(accounts); | ||
repeated_tx_reqs.extend(tx_reqs.into_iter()); | ||
} | ||
bm.submit_and_wait_txn_requests(&repeated_tx_reqs); | ||
} | ||
} | ||
|
||
/// Measure both `burst` and `epoch` throughput with pairwise TXN pattern. | ||
/// * `burst throughput`: the average committed txns per second during one run of playing TXNs | ||
/// (e.g., Benchmarker::submit_and_wait_txn_requests). Since time is counted from submission until | ||
/// all TXNs are committed, this measurement is in a sense the user-side throughput. In one epoch, | ||
/// we play the pairwise TXN request sequence repeatedly for num_rounds times. | ||
/// * `epoch throughput`: Since single run of playing TXNs may have high variance, we can repeat | ||
/// playing TXNs many times and calculate the averaged `burst throughput` along with standard | ||
/// deviation (will be added shortly). | ||
fn measure_throughput( | ||
bm: &mut Benchmarker, | ||
accounts: &mut [AccountData], | ||
num_rounds: u64, | ||
num_epochs: u64, | ||
) { | ||
let mut txn_throughput_seq = vec![]; | ||
for _ in 0..num_epochs { | ||
let mut repeated_tx_reqs = vec![]; | ||
for _ in 0..num_rounds { | ||
let tx_reqs = bm.gen_pairwise_txn_requests(accounts); | ||
repeated_tx_reqs.extend(tx_reqs.into_iter()); | ||
} | ||
let txn_throughput = bm.measure_txn_throughput(&repeated_tx_reqs); | ||
txn_throughput_seq.push(txn_throughput); | ||
} | ||
println!( | ||
"{:?} epoch(s) of TXN throughput = {:?}", | ||
num_epochs, txn_throughput_seq | ||
); | ||
} | ||
|
||
fn create_ac_client(conn_addr: &str) -> AdmissionControlClient { | ||
let env_builder = Arc::new(EnvBuilder::new().name_prefix("ac-grpc-").build()); | ||
let ch = ChannelBuilder::new(env_builder).connect(&conn_addr); | ||
AdmissionControlClient::new(ch) | ||
} | ||
|
||
/// Creat a vector of AdmissionControlClient and connect them to validators. | ||
pub fn create_ac_clients( | ||
num_clients: usize, | ||
validator_addresses: Vec<String>, | ||
) -> Vec<AdmissionControlClient> { | ||
let mut clients: Vec<AdmissionControlClient> = vec![]; | ||
for i in 0..num_clients { | ||
let index = i % validator_addresses.len(); | ||
let client = create_ac_client(&validator_addresses[index]); | ||
clients.push(client); | ||
} | ||
clients | ||
} | ||
|
||
fn main() { | ||
let _g = logger::set_default_global_logger(false, Some(256)); | ||
info!("RuBen: the utility to (Ru)n (Ben)chmarker"); | ||
let args = Opt::new_from_args(); | ||
info!("Parsed arguments: {:#?}", args); | ||
|
||
// Create AdmissionControlClient instances. | ||
let clients = create_ac_clients(args.num_clients, args.validator_addresses); | ||
|
||
// Create NodeDebugClient instance. | ||
let debug_client = NodeDebugClient::from_socket_addr_str( | ||
args.debug_address.expect("failed to parse debug_address"), | ||
); | ||
|
||
// Ready to instantiate Benchmarker. | ||
let mut bm = Benchmarker::new(clients, debug_client); | ||
let mut accounts: Vec<AccountData> = bm | ||
.gen_and_mint_accounts(&args.faucet_key_file_path, args.num_accounts) | ||
.expect("failed to generate and mint all accounts"); | ||
match args.executable { | ||
Executable::TestLiveness => { | ||
test_liveness(&mut bm, &mut accounts, args.num_rounds, args.num_epochs); | ||
} | ||
Executable::MeasureThroughput => { | ||
measure_throughput(&mut bm, &mut accounts, args.num_rounds, args.num_epochs); | ||
} | ||
}; | ||
} |
Oops, something went wrong.