diff --git a/sky-bench/src/benchtool/mod.rs b/sky-bench/src/benchtool/mod.rs index 1dfa6234..f2b23ac5 100644 --- a/sky-bench/src/benchtool/mod.rs +++ b/sky-bench/src/benchtool/mod.rs @@ -51,7 +51,7 @@ pub fn runner( json_out: bool, runs: usize, ) { - if util::possible_permutations(per_kv_size) < max_queries { + if !util::enough_ncr(per_kv_size, max_queries) { err!("Too low sample space for given k/v size and query count. Try a higher k/v size."); } diff --git a/sky-bench/src/main.rs b/sky-bench/src/main.rs index c1576fd5..c1b7c6c6 100644 --- a/sky-bench/src/main.rs +++ b/sky-bench/src/main.rs @@ -59,8 +59,8 @@ fn main() { None => 2003, }; let json_out = matches.is_present("json"); - let max_connections = match matches.value_of("connections").map(|v| v.parse::()) { - Some(Ok(con)) => con, + let max_connections = match matches.value_of("connections").map(|v| v.parse::()) { + Some(Ok(con)) => con as _, None => DEFAULT_WORKER_COUNT, _ => err!("Bad value for maximum connections"), }; diff --git a/sky-bench/src/util.rs b/sky-bench/src/util.rs index 7a62d9d2..60e47812 100644 --- a/sky-bench/src/util.rs +++ b/sky-bench/src/util.rs @@ -62,13 +62,6 @@ macro_rules! err { std::process::exit(0x01); }}; } -pub fn possible_permutations(r: usize) -> usize { - let mut ret = 1usize; - for i in (256 - r + 1)..=256 { - ret *= i; - } - ret -} /// Returns the number of queries/sec pub fn calc(reqs: usize, time: u128) -> f64 { @@ -93,8 +86,7 @@ pub fn run_sanity_test(host: &str, port: u16) -> Result<(), Box> { let mut query = Query::new(); query.push("heya"); if !connection - .run_query_raw(&query) - .unwrap() + .run_query_raw(&query)? .eq(&Element::String("HEY!".to_owned())) { return Err("HEYA test failed".into()); @@ -106,8 +98,7 @@ pub fn run_sanity_test(host: &str, port: u16) -> Result<(), Box> { query.push(&key); query.push(&value); if !connection - .run_query_raw(&query) - .unwrap() + .run_query_raw(&query)? .eq(&Element::RespCode(RespCode::Okay)) { return Err("SET test failed".into()); @@ -116,8 +107,7 @@ pub fn run_sanity_test(host: &str, port: u16) -> Result<(), Box> { query.push("get"); query.push(&key); if !connection - .run_query_raw(&query) - .unwrap() + .run_query_raw(&query)? .eq(&Element::Binstr(value.as_bytes().to_owned())) { return Err("GET test failed".into()); @@ -126,11 +116,52 @@ pub fn run_sanity_test(host: &str, port: u16) -> Result<(), Box> { query.push("del"); query.push(&key); if !connection - .run_query_raw(&query) - .unwrap() + .run_query_raw(&query)? .eq(&Element::UnsignedInt(1)) { return Err("DEL test failed".into()); } Ok(()) } + +/// Check if the provided keysize has enough combinations to support the given `queries` count +/// +/// This function is heavily optimized and should take Θ(1) time. The `ALWAYS_TRUE_FACTOR` is +/// dependent on pointer width (more specifically the virtual address space size). +/// - For 64-bit address spaces: `(256!)/r!(256-r!)`; for a value of r >= 12, we'll hit the maximum +/// of the address space and hence this will always return true (because of the size of `usize`) +/// > The value for r = 12 is `1.27309515e+20` which largely exceeds `1.8446744e+19` +/// - For 32-bit address spaces: `(256!)/r!(256-r!)`; for a value of r >= 5, we'll hit the maximum +/// of the address space and hence this will always return true (because of the size of `usize`) +/// > The value for r = 5 is `8.81e+9` which largely exceeds `4.3e+9` +pub const fn enough_ncr(keysize: usize, queries: usize) -> bool { + const LUT: [u64; 11] = [ + // 1B + 256, + // 2B + 32640, + // 3B + 2763520, + // 4B + 174792640, + // 5B + 8809549056, + // 6B + 368532802176, + // 7B + 13161885792000, + // 8B + 409663695276000, + // 9B + 11288510714272000, + // 10B + 278826214642518400, + // 11B + 6235568072914502400, + ]; + #[cfg(target_pointer_width = "64")] + const ALWAYS_TRUE_FACTOR: usize = 12; + #[cfg(target_pointer_width = "32")] + const ALWAYS_TRUE_FACTOR: usize = 5; + keysize >= ALWAYS_TRUE_FACTOR || (LUT[keysize - 1] >= queries as _) +}