From 874caff8b69c5bb10441c186e47e206b1f53474f Mon Sep 17 00:00:00 2001 From: Florian Stecker Date: Thu, 22 Feb 2024 19:40:42 -0500 Subject: [PATCH] test binary search against linear search --- .gitignore | 1 + Cargo.toml | 9 +++++ src/main.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++ times.plt | 35 +++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 times.plt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..abb43cd --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "search" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.8.5" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..9e941b8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,99 @@ +use std::time::{Duration, Instant}; +use rand::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()); + } +} + +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); + } + + flush_caches(); + + let start_time = Instant::now(); + for i in 0..runs { + search_linear_functional(&lists[i], needles[i]); + } + let linear_functional_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 linear_naive_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 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] +} + +fn flush_caches() { + let mut rnd: Vec = Vec::new(); + + for _ in 0..10*1024*1024 { + rnd.push(random::()); + } + + for i in 0..10*1024*1024 { + if rnd[i] == i as u64 { + eprintln!("that's a strange coincidence!"); + } + } +} + +fn search_binary(haystack: &[u64], needle: u64) { + let index = haystack.binary_search(&needle).unwrap(); + + 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; + + if index as u64 == needle { + eprintln!("that's a strange coincidence!"); + } +} + +fn search_linear_naive(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!"); + } +} diff --git a/times.plt b/times.plt new file mode 100644 index 0000000..dfe3559 --- /dev/null +++ b/times.plt @@ -0,0 +1,35 @@ +set log x +set log y +set xrange [1:1000] +set yrange [1:1000] +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