#[macro_use] extern crate json_in_type_derive; #[macro_use] extern crate serde_derive; use criterion::{AxisScale, Criterion, Fun, ParameterizedBenchmark, PlotConfiguration, Throughput}; use json_in_type::*; fn simple_json_in_type(n: f64) -> Vec { let obj = json_object! { void: (), list: json_list![1.,2.,3.,n], hello: "world" }; obj.to_json_buffer() } fn simple_serde(n: f64) -> Vec { let obj = serde_json::json!({ "void": null, "list": [1., 2., 3., n], "hello": "world" }); serde_json::to_vec(&obj).unwrap() } #[derive(Serialize, JSONValue)] struct MyObject { void: (), list: Vec, hello: String, } fn simple_serde_derive(n: f64) -> Vec { let obj = MyObject { void: (), list: vec![1., 2., 3., n], hello: String::from("world"), }; serde_json::to_vec(&obj).unwrap() } fn simple_json_in_type_derive(n: f64) -> Vec { let obj = MyObject { void: (), list: vec![1., 2., 3., n], hello: String::from("world"), }; obj.to_json_buffer() } fn nested_json_in_type(n: u8) -> Vec { // 8 levels of nested objects let obj = json_object! { nested: json_object! { nested: json_object! { nested: json_object! { nested: json_object! { nested: json_object! { nested: json_object! { nested: json_object! { nested: json_object! { value: n } } } } } } } } }; obj.to_json_buffer() } fn nested_serde(n: u8) -> Vec { let obj = serde_json::json!({ "nested": { "nested": { "nested": { "nested": { "nested": { "nested": { "nested": { "nested": { "value": n } } } } } } } } }); serde_json::to_vec(&obj).unwrap() } fn criterion_benchmark(c: &mut Criterion) { c.bench_functions( "encode simple object with macro", vec![ Fun::new("json_in_type", |b, i| b.iter(|| simple_json_in_type(*i))), Fun::new("serde_json", |b, i| b.iter(|| simple_serde(*i))), ], 999_999_999.999f64, ); c.bench_functions( "encode simple object with derive", vec![ Fun::new("json_in_type", |b, i| { b.iter(|| simple_json_in_type_derive(*i)) }), Fun::new("serde_json", |b, i| b.iter(|| simple_serde_derive(*i))), ], 999_999_999.999f64, ); c.bench_functions( "encode nested objects", vec![ Fun::new("json_in_type", |b, i| b.iter(|| nested_json_in_type(*i))), Fun::new("serde_json", |b, i| b.iter(|| nested_serde(*i))), ], 0, ); struct BenchStr(String); impl BenchStr { fn new(magnitude: usize) -> BenchStr { BenchStr( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. \ In vel erat rutrum, tincidunt lorem nullam\n" .repeat(1 << magnitude), ) } fn serde(&self) -> Vec { serde_json::to_vec(&self.0).unwrap() } fn json_in_type(&self) -> Vec { self.0.to_json_buffer() } fn bytes_len(&self) -> usize { self.0.as_bytes().len() } } impl std::fmt::Debug for BenchStr { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}-bytes string", self.bytes_len()) } } c.bench( "string encoding throughput", ParameterizedBenchmark::new( "json_in_type", |b, i| b.iter(|| i.json_in_type()), (0..12).step_by(4).map(BenchStr::new), ) .with_function("serde", |b, i| b.iter(|| i.serde())) .throughput(|i| Throughput::Bytes(i.bytes_len() as u32)) .plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic)), ); c.bench_functions( "string with many special chars", vec![ Fun::new("json_in_type", |b, i: &String| { b.iter(|| i.to_json_buffer()) }), Fun::new("serde", |b, i: &String| { b.iter(|| serde_json::to_vec(i).unwrap()) }), ], "\r\n\"Zero\"\r\n\t\"\0\" is the \"null\" byte.".repeat(1024), ); } criterion::criterion_group! { name = benches; config = Criterion::default().noise_threshold(0.05); targets = criterion_benchmark } criterion::criterion_main!(benches);