use std::time::{Duration, Instant}; use rand::{Rng, thread_rng, random}; fn main() { // generate 800MB of random data let mut data: Vec = vec![0; 100*1024*1024]; thread_rng().fill(&mut data[..]); let mut metadata: Vec<(usize, usize)> = Vec::new(); let mut all_times: Vec> = Vec::new(); for run in 0..4 { let mut run_times: Vec<(u128, u128, u128)> = Vec::with_capacity(200); for i in 0..200 { let runs = 10000000 / (i+1); let items = (i+1)*2; let result = test_searches(&data, runs, items); if run == 0 { metadata.push((runs, items)); } run_times.push((result[0].as_nanos(), result[1].as_nanos(), result[2].as_nanos())); } all_times.push(run_times); } for i in 0..metadata.len() { println!("{} {} {} {} {}", metadata[i].0, metadata[i].1, all_times.iter().map(|x|x[i].0).sum::(), all_times.iter().map(|x|x[i].1).sum::(), all_times.iter().map(|x|x[i].2).sum::()); } } fn test_searches(data: &[u64], runs: usize, items: usize) -> Vec { let needle_offset = random::(); // let offset_offset = random::(); let offset_offset = items; flush_caches(); let start_time = Instant::now(); for i in 0..runs { let offset = usize::wrapping_mul(i+1, offset_offset) % (data.len() - items); let needle = u64::wrapping_mul((i+1) as u64, needle_offset); search_linear_iter(&data[offset..offset+items], needle); } let linear_iter_duration = Instant::now().duration_since(start_time); flush_caches(); let start_time = Instant::now(); for i in 0..runs { let offset = usize::wrapping_mul(i+1, offset_offset) % (data.len() - items); let needle = u64::wrapping_mul((i+1) as u64, needle_offset); search_linear_loop(&data[offset..offset+items], needle); } let linear_loop_duration = Instant::now().duration_since(start_time); flush_caches(); let start_time = Instant::now(); for i in 0..runs { let offset = usize::wrapping_mul(i+1, offset_offset) % (data.len() - items); let needle = u64::wrapping_mul((i+1) as u64, needle_offset); search_binary(&data[offset..offset+items], needle); } let binary_duration = Instant::now().duration_since(start_time); eprintln!("Tested {} runs of {} items each", runs, items); vec![linear_iter_duration, linear_loop_duration, binary_duration] } fn flush_caches() { let mut data: Vec = vec![0; 1024*1024]; thread_rng().fill(&mut data[..]); for i in 0..data.len() { if data[i] == i as u64 { eprintln!("that's a strange coincidence!"); } } } fn search_binary(haystack: &[u64], needle: u64) { let index = haystack.binary_search(&needle).unwrap_or_else(|x|x); if index as u64 == needle { eprintln!("that's a strange coincidence!"); } } fn search_linear_iter(haystack: &[u64], needle: u64) { let index = haystack.iter() .enumerate() .skip_while(|(_,x)|**x != needle) .next() .map(|x|x.0) .unwrap_or_else(||haystack.len()); if index as u64 == needle { eprintln!("that's a strange coincidence!"); } } fn search_linear_loop(haystack: &[u64], needle: u64) { let mut index = 0; for i in 0..haystack.len() { if haystack[i] == needle { index = i; break; } }; if index as u64 == needle { eprintln!("that's a strange coincidence!"); } }