124 lines
3.2 KiB
Rust
124 lines
3.2 KiB
Rust
use std::time::{Duration, Instant};
|
|
use rand::{Rng, thread_rng, random};
|
|
|
|
fn main() {
|
|
// generate 800MB of random data
|
|
let mut data: Vec<u64> = vec![0; 100*1024*1024];
|
|
thread_rng().fill(&mut data[..]);
|
|
data.sort();
|
|
|
|
let mut metadata: Vec<(usize, usize)> = Vec::new();
|
|
let mut all_times: Vec<Vec<(u128, u128, u128)>> = Vec::new();
|
|
|
|
for run in 0..4 {
|
|
let mut run_times: Vec<(u128, u128, u128)> = Vec::with_capacity(200);
|
|
for i in 1..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::<u128>(),
|
|
all_times.iter().map(|x|x[i].1).sum::<u128>(),
|
|
all_times.iter().map(|x|x[i].2).sum::<u128>());
|
|
}
|
|
}
|
|
|
|
fn test_searches(data: &[u64], runs: usize, items: usize) -> Vec<Duration> {
|
|
let needles: Vec<usize> = (0..runs).map(|_|random::<usize>() % items).collect();
|
|
// let offsets: Vec<usize> = (0..runs).map(|_|random::<usize>() % (data.len() - items)).collect();
|
|
let offsets: Vec<usize> = (0..runs).map(|i|i*items).collect();
|
|
|
|
flush_caches();
|
|
|
|
let start_time = Instant::now();
|
|
for i in 0..runs {
|
|
let offset = offsets[i];
|
|
let needle_index = needles[i];
|
|
search_linear_iter(&data[offset..offset+items], data[offset+needle_index]);
|
|
}
|
|
let linear_iter_duration = Instant::now().duration_since(start_time);
|
|
|
|
flush_caches();
|
|
|
|
let start_time = Instant::now();
|
|
for i in 0..runs {
|
|
let offset = offsets[i];
|
|
let needle_index = needles[i];
|
|
search_linear_loop(&data[offset..offset+items], data[offset+needle_index]);
|
|
}
|
|
let linear_loop_duration = Instant::now().duration_since(start_time);
|
|
|
|
flush_caches();
|
|
|
|
let start_time = Instant::now();
|
|
for i in 0..runs {
|
|
let offset = offsets[i];
|
|
let needle_index = needles[i];
|
|
search_binary(&data[offset..offset+items], data[offset+needle_index]);
|
|
}
|
|
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]
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
fn flush_caches() {
|
|
let mut data: Vec<u64> = 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(|(i,_)|i)
|
|
.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!");
|
|
}
|
|
}
|