diff --git a/presets/benchmarks/example.toml b/presets/benchmarks/example.toml index 0843879..b9cb3ab 100644 --- a/presets/benchmarks/example.toml +++ b/presets/benchmarks/example.toml @@ -11,8 +11,6 @@ kmax = 1000 [[benchmark]] set_perc = 100 get_perc = 0 -del_perc = 0 -scan_perc = 0 repeat = 1 dist = "incrementp" @@ -20,14 +18,10 @@ dist = "incrementp" timeout = 0.2 set_perc = 50 get_perc = 50 -del_perc = 0 -scan_perc = 0 dist = "zipfian" [[benchmark]] timeout = 0.2 set_perc = 50 get_perc = 50 -del_perc = 0 -scan_perc = 0 dist = "uniform" diff --git a/presets/benchmarks/example_scan.toml b/presets/benchmarks/example_scan.toml index 3ea0cf1..9914240 100644 --- a/presets/benchmarks/example_scan.toml +++ b/presets/benchmarks/example_scan.toml @@ -12,8 +12,6 @@ kmax = 1000 [[benchmark]] set_perc = 100 get_perc = 0 -del_perc = 0 -scan_perc = 0 repeat = 1 dist = "incrementp" @@ -21,7 +19,6 @@ dist = "incrementp" timeout = 0.2 set_perc = 50 get_perc = 25 -del_perc = 0 scan_perc = 25 dist = "zipfian" @@ -29,6 +26,5 @@ dist = "zipfian" timeout = 0.2 set_perc = 50 get_perc = 25 -del_perc = 0 scan_perc = 25 dist = "uniform" diff --git a/src/bench.rs b/src/bench.rs index ba95db1..b8f45d7 100644 --- a/src/bench.rs +++ b/src/bench.rs @@ -362,7 +362,6 @@ pub struct GlobalOpt { pub latency: Option, pub cdf: Option, // workload - pub scan_n: Option, pub klen: Option, pub vlen: Option, pub kmin: Option, @@ -379,7 +378,6 @@ impl Default for GlobalOpt { report: None, latency: None, cdf: None, - scan_n: None, klen: None, vlen: None, kmin: None, @@ -407,12 +405,6 @@ impl GlobalOpt { .cdf .clone() .or_else(|| Some(self.cdf.clone().unwrap_or(false))); - // the workload options (fall back to defaults) - opt.workload.scan_n = opt - .workload - .scan_n - .clone() - .or_else(|| Some(self.scan_n.clone().unwrap_or(10))); // the workload options (must be specified) opt.workload.klen = opt .workload @@ -1112,7 +1104,6 @@ mod tests { report = "finish" latency = true cdf = true - scan_n = 500 klen = 8 vlen = 16 kmin = 100 @@ -1133,10 +1124,10 @@ mod tests { let wopt = WorkloadOpt { set_perc: 50, get_perc: 30, - del_perc: 10, - scan_perc: 10, + del_perc: Some(10), + scan_perc: Some(10), dist: "incrementp".to_string(), - scan_n: Some(500), + scan_n: None, klen: Some(8), vlen: Some(16), kmin: Some(100), @@ -1184,9 +1175,9 @@ mod tests { let wopt = WorkloadOpt { set_perc: 50, get_perc: 30, - del_perc: 10, - scan_perc: 10, - scan_n: Some(10), + del_perc: Some(10), + scan_perc: Some(10), + scan_n: None, dist: "shufflep".to_string(), klen: Some(8), vlen: Some(16), diff --git a/src/workload.rs b/src/workload.rs index bc7e55e..88de1f6 100644 --- a/src/workload.rs +++ b/src/workload.rs @@ -162,11 +162,11 @@ pub struct WorkloadOpt { /// Percentage of `GET` operations. pub get_perc: u8, - /// Percentage of `DELETE` operations. - pub del_perc: u8, + /// Percentage of `DELETE` operations (optional, default 0). + pub del_perc: Option, - /// Percentage of `SCAN` operations. - pub scan_perc: u8, + /// Percentage of `SCAN` operations (optional, default 0). + pub scan_perc: Option, /// The number of iterations per `SCAN` (only used when `scan_perc` is non-zero, default 10). pub scan_n: Option, @@ -229,12 +229,16 @@ pub struct Workload { impl Workload { pub fn new(opt: &WorkloadOpt, thread_info: Option<(usize, usize)>) -> Self { // input sanity checks + let set_perc = opt.set_perc; + let get_perc = opt.get_perc; + let del_perc = opt.del_perc.unwrap_or(0); + let scan_perc = opt.scan_perc.unwrap_or(0); assert_eq!( - opt.set_perc + opt.get_perc + opt.del_perc + opt.scan_perc, + set_perc + get_perc + del_perc + scan_perc, 100, "sum of ops in a mix should be 100" ); - let scan_n = opt.scan_n.expect("scan_n should be specified"); + let scan_n = opt.scan_n.unwrap_or(10); let klen = opt.klen.expect("klen should be specified"); let vlen = opt.vlen.expect("vlen should be specified"); let kmin = opt.kmin.expect("kmin should be specified"); @@ -256,7 +260,7 @@ impl Workload { (kminp, kmaxp) }; - let mix = Mix::new(opt.set_perc, opt.get_perc, opt.del_perc, opt.scan_perc); + let mix = Mix::new(set_perc, get_perc, del_perc, scan_perc); let kgen = match opt.dist.as_str() { "increment" => KeyGenerator::new_increment(klen, kmin, kmax), "incrementp" => { @@ -663,13 +667,27 @@ mod tests { let _ = Workload::new_from_toml_str(s, None); } + #[test] + fn workload_toml_defaults_are_applied() { + let s = r#"set_perc = 70 + get_perc = 30 + klen = 4 + vlen = 6 + dist = "zipfian" + kmin = 0 + kmax = 12345"#; + let w = Workload::new_from_toml_str(s, None); + assert_eq!(w.scan_n, 10); + assert!(matches!(w.kgen.dist, KeyDistribution::Zipfian(_, 0))); + } + #[test] fn workload_keygen_parallel() { let mut opt = WorkloadOpt { set_perc: 50, get_perc: 50, - del_perc: 0, - scan_perc: 0, + del_perc: None, + scan_perc: None, scan_n: Some(10), klen: Some(16), vlen: Some(100), @@ -704,8 +722,8 @@ mod tests { let mut opt = WorkloadOpt { set_perc: 100, get_perc: 0, - del_perc: 0, - scan_perc: 0, + del_perc: None, + scan_perc: None, scan_n: Some(10), klen: Some(16), vlen: Some(100), @@ -743,8 +761,8 @@ mod tests { let opt = WorkloadOpt { set_perc: 5, get_perc: 95, - del_perc: 0, - scan_perc: 0, + del_perc: None, + scan_perc: None, scan_n: Some(10), klen: Some(16), vlen: Some(100), @@ -790,8 +808,8 @@ mod tests { let opt = WorkloadOpt { set_perc: 50, get_perc: 50, - del_perc: 0, - scan_perc: 0, + del_perc: None, + scan_perc: None, scan_n: Some(10), klen: Some(16), vlen: Some(100), @@ -832,4 +850,49 @@ mod tests { } assert!(set < 5500000 && set > 4500000); } + + #[test] + fn workload_even_operations() { + let opt = WorkloadOpt { + set_perc: 25, + get_perc: 25, + del_perc: Some(25), + scan_perc: Some(25), + scan_n: None, + klen: Some(16), + vlen: Some(100), + dist: "uniform".to_string(), + kmin: Some(1000), + kmax: Some(2000), + zipf_theta: None, + zipf_hotspot: None, + }; + let mut workload = Workload::new(&opt, None); + let mut set = 0; + let mut get = 0; + let mut del = 0; + let mut scan = 0; + let mut rng = rand::thread_rng(); + for _ in 0..10000000 { + let op = workload.next(&mut rng); + match op { + Operation::Set { .. } => { + set += 1; + } + Operation::Get { .. } => { + get += 1; + } + Operation::Delete { .. } => { + del += 1; + } + Operation::Scan { .. } => { + scan += 1; + } + } + } + assert!(set > 2400000 && set < 2600000); + assert!(get > 2400000 && get < 2600000); + assert!(del > 2400000 && del < 2600000); + assert!(scan > 2400000 && scan < 2600000); + } }