use std::hint::black_box;
use criterion::{BatchSize, BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use moq_flate::{Decoder, Encoder};
use moq_json::diff;
use serde_json::{Map, Value, json};
fn telemetry(tick: u64) -> Value {
let t = tick as f64;
let lat = 37.7749 + (t * 0.0001).sin() * 0.01;
let lon = -122.4194 + (t * 0.0001).cos() * 0.01;
json!({
"device": {
"id": "veh-4417-a2",
"model": "Sentinel X2",
"firmware": "4.18.2-rc1",
"serial": "SNX2-0000-4417-A2C9",
"region": "us-west-2",
"fleet": "logistics-prod",
"tags": ["cold-chain", "long-haul", "priority"],
},
"config": {
"sample_hz": 1,
"upload_hz": 1,
"geofence": "bay-area",
"thresholds": { "temp_c": 8.0, "humidity": 85, "shock_g": 3.5, "battery_pct": 15 },
"contacts": ["ops@example.com", "fleet@example.com"],
},
"ts": 1_700_000_000 + tick,
"uptime_s": tick,
"location": {
"lat": (lat * 1e6).round() / 1e6,
"lon": (lon * 1e6).round() / 1e6,
"alt_m": 12 + (tick % 5),
"heading": (tick * 7) % 360,
"speed_kph": 40 + (tick % 25),
"fix": "3d",
"sats": 9 + (tick % 3),
},
"sensors": {
"temp_c": ((4.0 + (t * 0.05).sin() * 1.5) * 100.0).round() / 100.0,
"humidity": 60 + (tick % 10),
"shock_g": (((t * 0.3).sin().abs()) * 100.0).round() / 100.0,
"door_open": tick % 30 == 0,
},
"power": {
"battery_pct": 100 - (tick / 6) % 100,
"charging": false,
"voltage_mv": 12_400 - (tick % 50) as i64,
"current_ma": 850 + (tick % 120) as i64,
},
"network": {
"rssi_dbm": -70 - (tick % 15) as i64,
"type": "lte",
"bytes_up": 1_024 * tick,
"bytes_down": 256 * tick,
"latency_ms": 35 + (tick % 40),
},
"counters": {
"events": tick,
"errors": tick / 50,
"reconnects": tick / 120,
},
})
}
fn big_static(tick: u64) -> Value {
let routes: Vec<Value> = (0..80)
.map(|i| {
json!({
"id": format!("route-{i:04}"),
"cidr": format!("10.{}.{}.0/24", i / 16, i % 16),
"gateway": format!("10.0.{i}.1"),
"metric": 100 + i,
"enabled": true,
"tags": ["prod", "egress", "monitored"],
})
})
.collect();
json!({
"meta": { "version": "9.2.1", "node": "edge-router-77", "region": "us-east-1" },
"routes": routes,
"counters": {
"packets_in": 1_000_000 + tick * 137,
"packets_out": 990_000 + tick * 131,
"errors": tick / 7,
"uptime_s": tick,
},
})
}
fn merge_owned(target: &mut Value, patch: Value) {
let Value::Object(patch) = patch else {
*target = patch;
return;
};
if !target.is_object() {
*target = Value::Object(Map::new());
}
let map = target.as_object_mut().unwrap();
for (key, value) in patch {
if value.is_null() {
map.remove(&key);
} else {
merge_owned(map.entry(key).or_insert(Value::Null), value);
}
}
}
struct Fixture {
name: &'static str,
old: Value,
new: Value,
patch: Value,
snapshot_bytes: Vec<u8>,
patch_bytes: Vec<u8>,
snapshot_slice: Vec<u8>,
delta_slice: Vec<u8>,
new_slice: Vec<u8>,
}
impl Fixture {
fn new(name: &'static str, make: fn(u64) -> Value) -> Self {
let old = make(0);
let new = make(1);
let patch = diff(&old, &new).patch;
let snapshot_bytes = serde_json::to_vec(&old).unwrap();
let patch_bytes = serde_json::to_vec(&patch).unwrap();
let new_bytes = serde_json::to_vec(&new).unwrap();
let mut enc = Encoder::new();
let snapshot_slice = enc.frame(&snapshot_bytes).to_vec();
let delta_slice = enc.frame(&patch_bytes).to_vec();
let mut enc = Encoder::new();
enc.frame(&snapshot_bytes);
let new_slice = enc.frame(&new_bytes).to_vec();
Self {
name,
old,
new,
patch,
snapshot_bytes,
patch_bytes,
snapshot_slice,
delta_slice,
new_slice,
}
}
fn warm_encoder(&self) -> Encoder {
let mut enc = Encoder::new();
enc.frame(&self.snapshot_bytes);
enc
}
fn warm_decoder(&self) -> Decoder {
let mut dec = Decoder::new();
dec.frame(&self.snapshot_slice).unwrap();
dec
}
}
fn fixtures() -> Vec<Fixture> {
vec![
Fixture::new("telemetry", telemetry),
Fixture::new("big_static", big_static),
]
}
fn encode_patch(c: &mut Criterion) {
let mut group = c.benchmark_group("encode_patch");
for f in &fixtures() {
group.throughput(Throughput::Bytes(f.snapshot_bytes.len() as u64));
group.bench_with_input(BenchmarkId::from_parameter(f.name), f, |b, f| {
b.iter(|| black_box(diff(&f.old, &f.new)));
});
}
group.finish();
}
fn decode_patch(c: &mut Criterion) {
let mut group = c.benchmark_group("decode_patch");
for f in &fixtures() {
group.throughput(Throughput::Bytes(f.snapshot_bytes.len() as u64));
group.bench_with_input(BenchmarkId::new("json_patch", f.name), f, |b, f| {
b.iter_batched(
|| f.old.clone(),
|mut current| {
json_patch::merge(&mut current, &f.patch);
black_box(current);
},
BatchSize::SmallInput,
);
});
group.bench_with_input(BenchmarkId::new("merge_owned", f.name), f, |b, f| {
b.iter_batched(
|| (f.old.clone(), f.patch.clone()),
|(mut current, patch)| {
merge_owned(&mut current, patch);
black_box(current);
},
BatchSize::SmallInput,
);
});
}
group.finish();
}
fn deflate(c: &mut Criterion) {
let mut group = c.benchmark_group("deflate");
for f in &fixtures() {
group.throughput(Throughput::Bytes(f.patch_bytes.len() as u64));
group.bench_with_input(BenchmarkId::from_parameter(f.name), f, |b, f| {
b.iter_batched(
|| f.warm_encoder(),
|mut enc| black_box(enc.frame(&f.patch_bytes)),
BatchSize::SmallInput,
);
});
}
group.finish();
}
fn inflate(c: &mut Criterion) {
let mut group = c.benchmark_group("inflate");
for f in &fixtures() {
group.throughput(Throughput::Bytes(f.patch_bytes.len() as u64));
group.bench_with_input(BenchmarkId::from_parameter(f.name), f, |b, f| {
b.iter_batched(
|| f.warm_decoder(),
|mut dec| black_box(dec.frame(&f.delta_slice).unwrap()),
BatchSize::SmallInput,
);
});
}
group.finish();
}
fn marshal(c: &mut Criterion) {
let mut group = c.benchmark_group("marshal");
for f in &fixtures() {
group.bench_with_input(BenchmarkId::new("full", f.name), f, |b, f| {
b.iter(|| black_box(serde_json::to_vec(&f.new).unwrap()));
});
group.bench_with_input(BenchmarkId::new("patch", f.name), f, |b, f| {
b.iter(|| black_box(serde_json::to_vec(&f.patch).unwrap()));
});
}
group.finish();
}
fn producer(c: &mut Criterion) {
let mut group = c.benchmark_group("producer");
for f in &fixtures() {
group.throughput(Throughput::Bytes(f.snapshot_bytes.len() as u64));
group.bench_with_input(BenchmarkId::new("merge", f.name), f, |b, f| {
b.iter_batched(
|| f.warm_encoder(),
|mut enc| {
let patch = diff(&f.old, &f.new).patch;
let bytes = serde_json::to_vec(&patch).unwrap();
black_box(enc.frame(&bytes));
},
BatchSize::SmallInput,
);
});
group.bench_with_input(BenchmarkId::new("snapshot", f.name), f, |b, f| {
b.iter_batched(
|| f.warm_encoder(),
|mut enc| {
let bytes = serde_json::to_vec(&f.new).unwrap();
black_box(enc.frame(&bytes));
},
BatchSize::SmallInput,
);
});
}
group.finish();
}
fn consumer(c: &mut Criterion) {
let mut group = c.benchmark_group("consumer");
for f in &fixtures() {
group.throughput(Throughput::Bytes(f.snapshot_bytes.len() as u64));
group.bench_with_input(BenchmarkId::new("merge", f.name), f, |b, f| {
b.iter_batched(
|| (f.warm_decoder(), f.old.clone()),
|(mut dec, mut current)| {
let plain = dec.frame(&f.delta_slice).unwrap();
let patch: Value = serde_json::from_slice(&plain).unwrap();
json_patch::merge(&mut current, &patch);
black_box(current);
},
BatchSize::SmallInput,
);
});
group.bench_with_input(BenchmarkId::new("snapshot", f.name), f, |b, f| {
b.iter_batched(
|| f.warm_decoder(),
|mut dec| {
let plain = dec.frame(&f.new_slice).unwrap();
let value: Value = serde_json::from_slice(&plain).unwrap();
black_box(value);
},
BatchSize::SmallInput,
);
});
}
group.finish();
}
criterion_group!(
benches,
encode_patch,
decode_patch,
deflate,
inflate,
marshal,
producer,
consumer
);
criterion_main!(benches);