4 ms·
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 mos
by buster 7y ago
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)
- terhechte 7y agoFYI 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");
- zuzun 7y agoA 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.
- terhechte 7y agoThanks for the info, good to know!
- unlinked_dll 7y agoYou can make this a lot faster assuming the schema is fixed, and clean it up a bit with iterators. IE something like this #[derive(Copy,Clone,Deserialize)] struct Point { x: f64, y: f64, z: f64 } #[derive(Copy,Clone,Deserialize)] struct Schema { coordinates: Vector<Point> } fn main() -> Result<(), Box<dyn Error>> { let mut json_content = String::new(); File::open("1.json")? // don't need Path .read_to_string(&mut json_content)?; let schema = serde_json::from_str::<Schema>(&json_content)?; let len = schema.coordinates.length(); let (x, y, z) = schema.coordinates .iter() .fold((0.0, 0.0, 0.0), |(xsum, ysum, zsum), (x, y, z)|{ (xsym + x, ysum + y, zsum + z) }); println!("x: {}, y: {}, z: {}", x / len, y / len, z / len); Ok(()) }
- jiofih 7y agoWhile I appreciate the intent, that’s turning beautiful concise code into a very much less readable... thing. How much faster is that?
- dwb 7y agoIt 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.
- unlinked_dll 7y agoHaven’t benchmarked but in principle: 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.