use bytes::Bytes;
use criterion::{BatchSize, Criterion, black_box, criterion_group, criterion_main};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use socketioxide_core::{Value, parser::Parse};
use socketioxide_parser_common::CommonParser;
#[derive(Serialize, Deserialize)]
struct Data<T> {
str: String,
data: usize,
arr: Vec<u8>,
inner: T,
}
impl<T> Data<T> {
pub fn new(inner: T) -> Self {
Self {
arr: vec![10; 50],
data: 100,
str: "test".to_string(),
inner,
}
}
}
#[derive(Serialize, Deserialize)]
struct NestedDataWithBinaries {
foo: String,
inner: Data<Vec<Bytes>>,
}
impl NestedDataWithBinaries {
fn new() -> Self {
NestedDataWithBinaries {
foo: "bar".to_string(),
inner: Data::new(vec![
Bytes::from_static(&[
20, 120, 24, 2, 14, 3, 13, 31, 13, 45, 67
]);
10
]),
}
}
}
fn serde_decode<T: DeserializeOwned>(data: &str) -> T {
serde_json::from_str(black_box(data)).unwrap()
}
fn socketio_decode<T: DeserializeOwned>(data: &mut Value, with_event: bool) -> T {
CommonParser
.decode_value(black_box(data), with_event)
.unwrap()
}
fn benchmark_default(c: &mut Criterion) {
let mut group = c.benchmark_group("parser_common/decode_value_default");
group.bench_function("Decode classic input data with serde_json", |b| {
b.iter_batched_ref(
|| {
CommonParser
.encode_value(&Data::new("test".to_string()), None)
.unwrap()
},
|d| serde_decode::<(Data<String>,)>(d.as_str().unwrap()),
BatchSize::SmallInput,
)
});
group.bench_function("Decode classic input data with common parser", |b| {
b.iter_batched_ref(
|| {
CommonParser
.encode_value(&Data::new("test".to_string()), None)
.unwrap()
},
|d| socketio_decode::<Data<String>>(d, false),
BatchSize::SmallInput,
)
});
group.bench_function("Decode classic input data with serde_json and event", |b| {
b.iter_batched_ref(
|| {
CommonParser
.encode_value(&Data::new("test".to_string()), Some("event"))
.unwrap()
},
|d| serde_decode::<(String, Data<String>)>(d.as_str().unwrap()),
BatchSize::SmallInput,
)
});
group.bench_function(
"Decode classic input data with common parser and event",
|b| {
b.iter_batched_ref(
|| {
CommonParser
.encode_value(&Data::new("test".to_string()), Some("event"))
.unwrap()
},
|d| socketio_decode::<Data<String>>(d, true),
BatchSize::SmallInput,
)
},
);
}
fn benchmark_binary(c: &mut Criterion) {
let mut group = c.benchmark_group("parser_common/decode_value_binary");
group.bench_function("Decode binary input data with serde_json", |b| {
b.iter_batched_ref(
|| serde_json::to_string(&(NestedDataWithBinaries::new(),)).unwrap(),
|d| serde_decode::<(NestedDataWithBinaries,)>(d.as_str()),
BatchSize::SmallInput,
)
});
group.bench_function("Decode binary input data with common parser", |b| {
b.iter_batched_ref(
|| {
CommonParser
.encode_value(&NestedDataWithBinaries::new(), None)
.unwrap()
},
|d| socketio_decode::<NestedDataWithBinaries>(d, false),
BatchSize::SmallInput,
)
});
group.bench_function("Decode binary input data with serde_json and event", |b| {
b.iter_batched_ref(
|| serde_json::to_string(&("event", NestedDataWithBinaries::new())).unwrap(),
|d| serde_decode::<(String, NestedDataWithBinaries)>(d.as_str()),
BatchSize::SmallInput,
)
});
group.bench_function(
"Decode binary input data with common parser and event",
|b| {
b.iter_batched_ref(
|| {
CommonParser
.encode_value(&NestedDataWithBinaries::new(), Some("event"))
.unwrap()
},
|d| socketio_decode::<NestedDataWithBinaries>(d, true),
BatchSize::SmallInput,
)
},
);
}
criterion_group!(benches, benchmark_default, benchmark_binary);
criterion_main!(benches);