From feadef4723c9b4f7f1185264a70e9b8545156636 Mon Sep 17 00:00:00 2001 From: Florian Stecker Date: Fri, 23 Feb 2024 01:04:49 -0500 Subject: [PATCH] some more careful caching prevention --- src/main.rs | 96 ++++++++++++++++++++++++++++++++--------------------- times.plt | 34 ++++--------------- 2 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9e941b8..07cb186 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,90 +1,112 @@ use std::time::{Duration, Instant}; -use rand::random; +use rand::{Rng, thread_rng, random}; fn main() { - for i in 1..400 { - let result = test_searches(500000 / i, i*2); - println!("{} {} {}", - result[0].as_nanos(), result[1].as_nanos(), result[2].as_nanos()); + // 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(runs: usize, items: usize) -> Vec { - let mut lists: Vec> = Vec::new(); - let mut needles: Vec = Vec::new(); - - for _ in 0..runs { - let mut current_list: Vec = Vec::new(); - - for _ in 0..items { - current_list.push(random::()); - } - - needles.push(current_list[0]); - current_list.sort(); - lists.push(current_list); - } +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 { - search_linear_functional(&lists[i], needles[i]); + 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_functional_duration = Instant::now().duration_since(start_time); + let linear_iter_duration = Instant::now().duration_since(start_time); flush_caches(); let start_time = Instant::now(); for i in 0..runs { - search_linear_naive(&lists[i], needles[i]); + 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_naive_duration = Instant::now().duration_since(start_time); + let linear_loop_duration = Instant::now().duration_since(start_time); flush_caches(); let start_time = Instant::now(); for i in 0..runs { - search_binary(&lists[i], needles[i]); + 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_functional_duration, linear_naive_duration, binary_duration] + vec![linear_iter_duration, linear_loop_duration, binary_duration] } fn flush_caches() { - let mut rnd: Vec = Vec::new(); + let mut data: Vec = vec![0; 1024*1024]; + thread_rng().fill(&mut data[..]); - for _ in 0..10*1024*1024 { - rnd.push(random::()); - } - - for i in 0..10*1024*1024 { - if rnd[i] == i as u64 { + 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(); + 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_functional(haystack: &[u64], needle: u64) { - let index = haystack.iter().enumerate().skip_while(|(_,x)|**x != needle).next().unwrap().0; +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_naive(haystack: &[u64], needle: u64) { +fn search_linear_loop(haystack: &[u64], needle: u64) { let mut index = 0; for i in 0..haystack.len() { if haystack[i] == needle { diff --git a/times.plt b/times.plt index dfe3559..edfff2b 100644 --- a/times.plt +++ b/times.plt @@ -1,35 +1,15 @@ set log x set log y set xrange [1:1000] -set yrange [1:1000] +set yrange [1:3000] set grid set terminal pngcairo size 1024, 1024 set output "times.png" -# plot "data_new" using (($0+1)*2):($1*1.0/(500000/($0+1))) w l lw 2 lc 1 t "linear, iterator", \ -# "data_new" using (($0+1)*2):($2*1.0/(500000/($0+1))) w l lw 2 lc 2 t "linear, for loop", \ -# "data_new" using (($0+1)*2):($3*1.0/(500000/($0+1))) w l lw 2 lc 3 t "binary", \ -# "data_new2" using (($0+1)*2):($1*1.0/(500000/($0+1))) w l lw 2 lc 1 t "", \ -# "data_new2" using (($0+1)*2):($2*1.0/(500000/($0+1))) w l lw 2 lc 2 t "", \ -# "data_new2" using (($0+1)*2):($3*1.0/(500000/($0+1))) w l lw 2 lc 3 t "", \ -# "data_new3" using (($0+1)*2):($1*1.0/(500000/($0+1))) w l lw 2 lc 1 t "", \ -# "data_new3" using (($0+1)*2):($2*1.0/(500000/($0+1))) w l lw 2 lc 2 t "", \ -# "data_new3" using (($0+1)*2):($3*1.0/(500000/($0+1))) w l lw 2 lc 3 t "", \ -# "data_new4" using (($0+1)*2):($1*1.0/(500000/($0+1))) w l lw 2 lc 1 t "", \ -# "data_new4" using (($0+1)*2):($2*1.0/(500000/($0+1))) w l lw 2 lc 2 t "", \ -# "data_new4" using (($0+1)*2):($3*1.0/(500000/($0+1))) w l lw 2 lc 3 t "", \ - -plot "data_new_avg" using (($0+1)*2):($1) w l lw 2 lc 1 t "linear search, iterator", \ - "data_new_avg" using (($0+1)*2):($2) w l lw 2 lc 2 t "linear search, loop", \ - "data_new_avg" using (($0+1)*2):($3) w l lw 2 lc 3 t "binary search", \ - -# plot "data" using (($0+1)*1 ):($1/($0+1)/10000) w p pt 7 lc 1 t "linear functional", \ -# "data" using (($0+1)*1 ):($2/($0+1)/10000) w p pt 7 lc 2 t "linear naive", \ -# "data" using (($0+1)*1 ):($3/($0+1)/10000) w p pt 7 lc 3 t "binary", \ -# "data_big" using (($0+1)*100):($1/($0+1)/1000000) w p pt 7 lc 1 t "", \ -# "data_big" using (($0+1)*100):($2/($0+1)/1000000) w p pt 7 lc 2 t "", \ -# "data_big" using (($0+1)*100):($3/($0+1)/1000000) w p pt 7 lc 3 t "" - -# pause mouse keypress -# reread +plot "data_c8" using 2:($3/$1/4) w l lw 2 t "linear, iterator, consecutive", \ + "" using 2:($4/$1/4) w l lw 2 t "linear, loop, consecutive", \ + "" using 2:($5/$1/4) w l lw 2 t "binary, consecutive", \ + "data_c7" using 2:($3/$1/4) w l lw 2 t "linear, iterator, spread", \ + "" using 2:($4/$1/4) w l lw 2 t "linear, loop, spread", \ + "" using 2:($5/$1/4) w l lw 2 t "binary, spread"