// Copyright 2017 Alkis Evlogimenos // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #![feature(test)] extern crate ordslice; extern crate rand; extern crate test; use rand::distributions::Range; use rand::distributions::IndependentSample; use ordslice::Ext; use test::Bencher; enum Cache { L1, L2, L3, } enum Config { Unique, Dups, } impl Cache { pub fn size(&self) -> usize { match *self { Cache::L1 => 1000, // 8kb Cache::L2 => 10_000, // 80kb Cache::L3 => 1_000_000, // 8Mb } } } macro_rules! for_each_config { () => ( #[bench] fn unique(b: &mut Bencher) { run(b, Config::Unique); } #[bench] fn dups(b: &mut Bencher) { run(b, Config::Dups); } ) } macro_rules! for_each_cache { () => ( mod l1 { use super::*; fn run(b: &mut Bencher, config: Config) { super::run(b, Cache::L1, config) } for_each_config!(); } mod l2 { use super::*; fn run(b: &mut Bencher, config: Config) { super::run(b, Cache::L2, config) } for_each_config!(); } mod l3 { use super::*; fn run(b: &mut Bencher, config: Config) { super::run(b, Cache::L3, config) } for_each_config!(); } ) } fn generate_inputs(cache: Cache, config: Config) -> (Vec, Vec) { let size = cache.size(); let between = Range::new(0, size * 16); let mut rng = rand::thread_rng(); let mut sample = || { let x = between.ind_sample(&mut rng); match config { Config::Dups => x / 16 * 16, Config::Unique => x, } }; let mut values = (0..size).map(|_| sample()).collect::>(); values.sort(); let mut lookups = Vec::with_capacity(size); for _ in 0..size { lookups.push(sample()); } (values, lookups) } mod lower_bound { use super::*; fn run(b: &mut Bencher, cache: Cache, config: Config) { let (values, lookups) = generate_inputs(cache, config); let mut iter = lookups.iter().cycle(); b.iter(|| { values.lower_bound(iter.next().unwrap()) }) } for_each_cache!(); } mod upper_bound { use super::*; fn run(b: &mut Bencher, cache: Cache, config: Config) { let (values, lookups) = generate_inputs(cache, config); let mut iter = lookups.iter().cycle(); b.iter(|| { values.upper_bound(iter.next().unwrap()) }) } for_each_cache!(); } mod equal_range { use super::*; fn run(b: &mut Bencher, cache: Cache, config: Config) { let (values, lookups) = generate_inputs(cache, config); let mut iter = lookups.iter().cycle(); b.iter(|| { values.equal_range(iter.next().unwrap()) }) } for_each_cache!(); }