Add conflict groups to bench-tps (#29513)
* Add conflict groups to bench-tps * Add tests for KeyChunks initialization * Add validation for num-conflict-groups * Refactor of destination key generation * Clarify in comments it is slice, not vector * Use repeat_with in tests
This commit is contained in:
parent
d463bcc5f8
commit
9fa3cb659c
|
@ -74,13 +74,31 @@ struct KeypairChunks<'a> {
|
|||
}
|
||||
|
||||
impl<'a> KeypairChunks<'a> {
|
||||
/// Split input vector of keypairs into two sets of chunks of given size
|
||||
/// Split input slice of keypairs into two sets of chunks of given size
|
||||
fn new(keypairs: &'a [Keypair], chunk_size: usize) -> Self {
|
||||
// Use `chunk_size` as the number of conflict groups per chunk so that each destination key is unique
|
||||
Self::new_with_conflict_groups(keypairs, chunk_size, chunk_size)
|
||||
}
|
||||
|
||||
/// Split input slice of keypairs into two sets of chunks of given size. Each chunk
|
||||
/// has a set of source keys and a set of destination keys. There will be
|
||||
/// `num_conflict_groups_per_chunk` unique destination keys per chunk, so that the
|
||||
/// destination keys may conflict with each other.
|
||||
fn new_with_conflict_groups(
|
||||
keypairs: &'a [Keypair],
|
||||
chunk_size: usize,
|
||||
num_conflict_groups_per_chunk: usize,
|
||||
) -> Self {
|
||||
let mut source_keypair_chunks: Vec<Vec<&Keypair>> = Vec::new();
|
||||
let mut dest_keypair_chunks: Vec<VecDeque<&Keypair>> = Vec::new();
|
||||
for chunk in keypairs.chunks_exact(2 * chunk_size) {
|
||||
source_keypair_chunks.push(chunk[..chunk_size].iter().collect());
|
||||
dest_keypair_chunks.push(chunk[chunk_size..].iter().collect());
|
||||
dest_keypair_chunks.push(
|
||||
std::iter::repeat(&chunk[chunk_size..chunk_size + num_conflict_groups_per_chunk])
|
||||
.flatten()
|
||||
.take(chunk_size)
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
KeypairChunks {
|
||||
source: source_keypair_chunks,
|
||||
|
@ -110,8 +128,13 @@ where
|
|||
chunk_size: usize,
|
||||
use_randomized_compute_unit_price: bool,
|
||||
instruction_padding_config: Option<InstructionPaddingConfig>,
|
||||
num_conflict_groups: Option<usize>,
|
||||
) -> Self {
|
||||
let account_chunks = KeypairChunks::new(gen_keypairs, chunk_size);
|
||||
let account_chunks = if let Some(num_conflict_groups) = num_conflict_groups {
|
||||
KeypairChunks::new_with_conflict_groups(gen_keypairs, chunk_size, num_conflict_groups)
|
||||
} else {
|
||||
KeypairChunks::new(gen_keypairs, chunk_size)
|
||||
};
|
||||
let nonce_chunks =
|
||||
nonce_keypairs.map(|nonce_keypairs| KeypairChunks::new(nonce_keypairs, chunk_size));
|
||||
|
||||
|
@ -353,6 +376,7 @@ where
|
|||
use_randomized_compute_unit_price,
|
||||
use_durable_nonce,
|
||||
instruction_padding_config,
|
||||
num_conflict_groups,
|
||||
..
|
||||
} = config;
|
||||
|
||||
|
@ -364,6 +388,7 @@ where
|
|||
tx_count,
|
||||
use_randomized_compute_unit_price,
|
||||
instruction_padding_config,
|
||||
num_conflict_groups,
|
||||
);
|
||||
|
||||
let first_tx_count = loop {
|
||||
|
@ -1160,4 +1185,60 @@ mod tests {
|
|||
}
|
||||
withdraw_durable_nonce_accounts(client, &authority_keypairs, &nonce_keypairs)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bench_tps_key_chunks_new() {
|
||||
let num_keypairs = 16;
|
||||
let chunk_size = 4;
|
||||
let keypairs = std::iter::repeat_with(Keypair::new)
|
||||
.take(num_keypairs)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let chunks = KeypairChunks::new(&keypairs, chunk_size);
|
||||
assert_eq!(
|
||||
chunks.source[0],
|
||||
&[&keypairs[0], &keypairs[1], &keypairs[2], &keypairs[3]]
|
||||
);
|
||||
assert_eq!(
|
||||
chunks.dest[0],
|
||||
&[&keypairs[4], &keypairs[5], &keypairs[6], &keypairs[7]]
|
||||
);
|
||||
assert_eq!(
|
||||
chunks.source[1],
|
||||
&[&keypairs[8], &keypairs[9], &keypairs[10], &keypairs[11]]
|
||||
);
|
||||
assert_eq!(
|
||||
chunks.dest[1],
|
||||
&[&keypairs[12], &keypairs[13], &keypairs[14], &keypairs[15]]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bench_tps_key_chunks_new_with_conflict_groups() {
|
||||
let num_keypairs = 16;
|
||||
let chunk_size = 4;
|
||||
let num_conflict_groups = 2;
|
||||
let keypairs = std::iter::repeat_with(Keypair::new)
|
||||
.take(num_keypairs)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let chunks =
|
||||
KeypairChunks::new_with_conflict_groups(&keypairs, chunk_size, num_conflict_groups);
|
||||
assert_eq!(
|
||||
chunks.source[0],
|
||||
&[&keypairs[0], &keypairs[1], &keypairs[2], &keypairs[3]]
|
||||
);
|
||||
assert_eq!(
|
||||
chunks.dest[0],
|
||||
&[&keypairs[4], &keypairs[5], &keypairs[4], &keypairs[5]]
|
||||
);
|
||||
assert_eq!(
|
||||
chunks.source[1],
|
||||
&[&keypairs[8], &keypairs[9], &keypairs[10], &keypairs[11]]
|
||||
);
|
||||
assert_eq!(
|
||||
chunks.dest[1],
|
||||
&[&keypairs[12], &keypairs[13], &keypairs[12], &keypairs[13]]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use {
|
||||
crate::spl_convert::FromOtherSolana,
|
||||
clap::{crate_description, crate_name, App, Arg, ArgMatches},
|
||||
solana_clap_utils::input_validators::{is_url, is_url_or_moniker},
|
||||
solana_clap_utils::input_validators::{is_url, is_url_or_moniker, is_within_range},
|
||||
solana_cli_config::{ConfigInput, CONFIG_FILE},
|
||||
solana_sdk::{
|
||||
fee_calculator::FeeRateGovernor,
|
||||
|
@ -65,6 +65,7 @@ pub struct Config {
|
|||
pub use_randomized_compute_unit_price: bool,
|
||||
pub use_durable_nonce: bool,
|
||||
pub instruction_padding_config: Option<InstructionPaddingConfig>,
|
||||
pub num_conflict_groups: Option<usize>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
@ -95,6 +96,7 @@ impl Default for Config {
|
|||
use_randomized_compute_unit_price: false,
|
||||
use_durable_nonce: false,
|
||||
instruction_padding_config: None,
|
||||
num_conflict_groups: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +344,13 @@ pub fn build_args<'a>(version: &'_ str) -> App<'a, '_> {
|
|||
.takes_value(true)
|
||||
.help("If set, wraps all instructions in the instruction padding program, with the given amount of padding bytes in instruction data."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("num_conflict_groups")
|
||||
.long("num-conflict-groups")
|
||||
.takes_value(true)
|
||||
.validator(|arg| is_within_range(arg, 1, usize::MAX - 1))
|
||||
.help("The number of unique destination accounts per transactions 'chunk'. Lower values will result in more transaction conflicts.")
|
||||
)
|
||||
}
|
||||
|
||||
/// Parses a clap `ArgMatches` structure into a `Config`
|
||||
|
@ -494,5 +503,13 @@ pub fn extract_args(matches: &ArgMatches) -> Config {
|
|||
});
|
||||
}
|
||||
|
||||
if let Some(num_conflict_groups) = matches.value_of("num_conflict_groups") {
|
||||
args.num_conflict_groups = Some(
|
||||
num_conflict_groups
|
||||
.parse()
|
||||
.expect("Can't parse conflict groups"),
|
||||
);
|
||||
}
|
||||
|
||||
args
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue