I was curious to reproduce the "benchmark" in rust, which got me to this code. Mind you, i have not much experienace in rust, so i'd think this would be the most straight forward translation of the nim code in the blog post for a beginner.
use std::fs::File;
use std::io::Read;
use std::path::Path;
use serde_json::Value;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut json_file = File::open(Path::new("1.json"))?;
let mut json_content = String::new();
json_file.read_to_string(&mut json_content)?;
let json_value : Value = serde_json::from_str(json_content.as_str())?;
let coords = json_value["coordinates"].as_array().expect("Coordinates");
let len: f64 = coords.len() as f64;
let mut x: f64 = 0.0;
let mut y: f64 = 0.0;
let mut z: f64 = 0.0;
for value in coords {
x = x + &value["x"].as_f64().expect("X Conversion");
y = y + &value["y"].as_f64().expect("y Conversion");
z = z + &value["z"].as_f64().expect("z Conversion");
}
println!("{}", x / len);
println!("{}", z / len);
println!("{}", z / len);
Ok(())
}
(fyi: the program ran in 2 seconds on my 7 year old laptop)
It would be more polite and accurate to express that as your opinion rather than objective fact. Personally, I prefer to read the second version. I also expect the techniques shown in it, especially parsing against a type-level schema, would be less error-prone than the original in a larger program.
Serde is one of the fastest deserializers out there. It excels when it has a defined schema to decode, using the #[derive] syntax should offload the work of the deserializer immensely and negate the effects of looking up fields which may not exist.
As well, using rust’s iterator adaptors like fold can allow the compiler to make better optimizations for things like summing vectors of floats, such as SIMD/auto vectorizing easier. It’s also better at eliminating or reducing bounds checks.
Using iterator abstractions is much more “beautiful” in my opinion to for loops, as well in rust tends to generate better assembly than indexing into collections like slices and vectors.
FYI you can read directly from a file without reading into a buf first. This might be a bit faster:
let json_file = File::open(json_file_path).expect("file not found");
let deserialized_camera: SomeDataType =
serde_json::from_reader(json_file).expect("error while reading json");
A year ago I did some benchmarks and found that from_reader is much slower than from_slice. There's now a note in the serde_json docs, so it still seems to be an issue.
I guess std::fs::read + serde_json::from_slice is the fastest way to do it, because it avoids the from_reader slowness and an UTF-8 validation.