use std::time::Instant;
#[derive(Clone, Copy)]
struct GlazePretty;
impl structio::Options for GlazePretty {
const PRETTY: bool = true;
const INDENT: usize = 3;
}
#[derive(Default)]
#[allow(non_snake_case)]
struct TestStruct {
testStrings: Vec<String>,
testUints: Vec<u64>,
testDoubles: Vec<f64>,
testInts: Vec<i64>,
testBools: Vec<bool>,
}
structio::object!(TestStruct {
testStrings,
testUints,
testDoubles,
testInts,
testBools
});
#[derive(Default)]
#[rustfmt::skip]
struct TestGenerator {
a: Vec<TestStruct>, b: Vec<TestStruct>, c: Vec<TestStruct>, d: Vec<TestStruct>,
e: Vec<TestStruct>, f: Vec<TestStruct>, g: Vec<TestStruct>, h: Vec<TestStruct>,
i: Vec<TestStruct>, j: Vec<TestStruct>, k: Vec<TestStruct>, l: Vec<TestStruct>,
m: Vec<TestStruct>, n: Vec<TestStruct>, o: Vec<TestStruct>, p: Vec<TestStruct>,
q: Vec<TestStruct>, r: Vec<TestStruct>, s: Vec<TestStruct>, t: Vec<TestStruct>,
u: Vec<TestStruct>, v: Vec<TestStruct>, w: Vec<TestStruct>, x: Vec<TestStruct>,
y: Vec<TestStruct>, z: Vec<TestStruct>,
}
#[rustfmt::skip]
structio::object!(TestGenerator {
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
});
fn run(label: &str, path: &str) {
let json = match std::fs::read_to_string(path) {
Ok(s) => s,
Err(e) => {
eprintln!("could not read {path}: {e} (run tmp/bench_glaze first)");
return;
}
};
let iters = (40_000_000 / json.len()).max(20);
let mut dst = TestGenerator::default();
structio::read_into(&mut dst, &json).expect("parse failed");
let t0 = Instant::now();
for _ in 0..iters {
structio::read_into(&mut dst, &json).expect("parse failed");
}
let read_s = t0.elapsed().as_secs_f64();
let mut out = String::with_capacity(json.len() * 2);
structio::write_into(&dst, &mut out);
let t0 = Instant::now();
for _ in 0..iters {
structio::write_into(&dst, &mut out);
}
let write_s = t0.elapsed().as_secs_f64();
let mut pretty = String::with_capacity(json.len() * 2);
structio::prettify_into_with::<GlazePretty>(&json, &mut pretty).expect("prettify failed");
let t0 = Instant::now();
for _ in 0..iters {
structio::prettify_into_with::<GlazePretty>(&json, &mut pretty).expect("prettify failed");
}
let pretty_s = t0.elapsed().as_secs_f64();
let glaze_pretty = std::fs::read_to_string(path.replace(".json", "_pretty.json")).ok();
let laid_out = glaze_pretty.as_deref().unwrap_or(&pretty);
let mut mini = String::with_capacity(json.len());
structio::minify_into(laid_out, &mut mini).expect("minify failed");
let t0 = Instant::now();
for _ in 0..iters {
structio::minify_into(laid_out, &mut mini).expect("minify failed");
}
let minify_s = t0.elapsed().as_secs_f64();
let mb = json.len() as f64 * iters as f64 / 1_048_576.0;
let laid_out_mb = laid_out.len() as f64 * iters as f64 / 1_048_576.0;
println!(
"{label:<9} {:7} B read {:8.2} MB/s write {:8.2} MB/s pretty {:8.2} MB/s minify {:8.2} MB/s {}{}{}",
json.len(),
mb / read_s,
mb / write_s,
mb / pretty_s,
laid_out_mb / minify_s,
if out == json {
""
} else {
"(ROUNDTRIP DIFFERS) "
},
match &glaze_pretty {
Some(want) if *want != pretty => "(PRETTY DIFFERS FROM GLAZE) ",
_ => "",
},
if mini == json {
""
} else {
"(MINIFY DIFFERS) "
}
);
}
fn main() {
println!("--- structio ---");
for (label, path) in [
("mixed", "tmp/bench.json"),
("strings", "tmp/bench_strings.json"),
("uints", "tmp/bench_uints.json"),
("doubles", "tmp/bench_doubles.json"),
("ints", "tmp/bench_ints.json"),
("bools", "tmp/bench_bools.json"),
("nice-dbl", "tmp/bench_nice_doubles.json"),
] {
run(label, path);
}
}