Skip to content

Instantly share code, notes, and snippets.

@flippingbitss
Created November 9, 2024 05:54
Show Gist options
  • Save flippingbitss/8551b0d915ac22ff252834e0d619a5c1 to your computer and use it in GitHub Desktop.
Save flippingbitss/8551b0d915ac22ff252834e0d619a5c1 to your computer and use it in GitHub Desktop.
the-haversine-distance-problem from computerenhance.com
use serde::Deserialize;
use std::{
fs::File,
io::{BufReader, Read},
time::Instant,
};
#[derive(Deserialize)]
struct Pair {
x0: f32,
y0: f32,
x1: f32,
y1: f32,
}
#[derive(Deserialize)]
struct Data {
pairs: Vec<Pair>,
}
fn haversine(p: &Pair, r: f32) -> f32 {
let dy = (p.y1 - p.y0).to_radians();
let dx = (p.x1 - p.x0).to_radians();
let y0 = (p.y0).to_radians();
let y1 = (p.y1).to_radians();
let root_term = f32::powi(f32::sin(dy / 2.), 2)
+ f32::cos(y0) * f32::cos(y1) * f32::powi(f32::sin(dx / 2.), 2);
let result = 2. * r * f32::asin(f32::sqrt(root_term));
result
}
const EARTH_RADIUS_KM: f32 = 6371.;
const FILE_PATH: &'static str = "../data_10000000_flex.json";
fn main() -> std::io::Result<()> {
let mut buf = String::new();
let mut reader = BufReader::new(File::open(FILE_PATH)?);
let start_time = Instant::now();
// Read file
reader.read_to_string(&mut buf)?;
// Parse json
let data: Data = serde_json::from_str(&buf)?;
let mid_time = Instant::now();
let len = data.pairs.len();
let sum = data
.pairs
.iter()
.map(|pair| haversine(&pair, EARTH_RADIUS_KM))
.sum::<f32>();
let avg = sum / len as f32;
let end_time = Instant::now();
println!("Result: {}", avg);
println!("Input = {} seconds", (mid_time - start_time).as_secs_f32());
println!("Math = {} seconds", (end_time - mid_time).as_secs_f32());
println!("Total = {} seconds", (end_time - start_time).as_secs_f32());
println!(
"Throughput = {} haversines/second",
(len as f32 / (end_time - start_time).as_secs_f32())
);
Ok(())
}
@flippingbitss
Copy link
Author

Specs: Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz, 16 GB RAM

Python 3.12.6 (python main.py)

Result: 6942.383649138654
Input = 19.53985857963562 seconds
Math = 8.20471477508545 seconds
Total = 27.74457335472107 seconds
Throughput = 360430.84433656937 haversines/second

Rust 1.78 (cargo run --release)

Result: 6932.284
Input = 2.5232582 seconds
Math = 0.37725833 seconds
Total = 2.9005165 seconds
Throughput = 3447661.8 haversines/second

Improvement: 9.5x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment