#![allow(
missing_docs,
clippy::doc_markdown,
clippy::expect_used,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use matter_codec::{Tag, TlvReader, TlvWriter};
fn build_byte_array(n: usize, elem: usize) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_array(Tag::Anonymous).expect("start array");
let data = vec![0xABu8; elem];
for _ in 0..n {
w.put_bytes(Tag::Anonymous, &data).expect("put bytes");
}
w.end_container().expect("end array");
buf
}
fn build_uint_array(n: usize) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_array(Tag::Anonymous).expect("start array");
for i in 0..n {
w.put_uint(Tag::Anonymous, i as u64).expect("put uint");
}
w.end_container().expect("end array");
buf
}
fn build_wide_struct(n: usize) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).expect("start struct");
for i in 0..n {
w.put_uint(Tag::Context((i % 255) as u8), i as u64)
.expect("put uint");
}
w.end_container().expect("end struct");
buf
}
fn build_nested(depth: usize) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
for i in 0..depth {
w.start_structure(if i == 0 {
Tag::Anonymous
} else {
Tag::Context(0)
})
.expect("start struct");
w.put_uint(Tag::Context(1), i as u64).expect("put uint");
}
for _ in 0..depth {
w.end_container().expect("end struct");
}
buf
}
fn build_report_shape(n_attrs: usize, val_len: usize) -> Vec<u8> {
let mut buf = Vec::new();
let mut w = TlvWriter::new(&mut buf);
w.start_structure(Tag::Anonymous).expect("msg");
w.start_array(Tag::Context(1)).expect("AttributeReports");
let data = vec![0xCDu8; val_len];
for i in 0..n_attrs {
w.start_structure(Tag::Anonymous).expect("IB");
w.start_structure(Tag::Context(1)).expect("AttributeData");
w.start_list(Tag::Context(1)).expect("Path");
w.put_uint(Tag::Context(2), 1).expect("endpoint");
w.put_uint(Tag::Context(3), 0x0006).expect("cluster");
w.put_uint(Tag::Context(4), i as u64).expect("attribute");
w.end_container().expect("end path");
w.put_bytes(Tag::Context(2), &data).expect("Data");
w.end_container().expect("end AttributeData");
w.end_container().expect("end IB");
}
w.end_container().expect("end array");
w.end_container().expect("end msg");
buf
}
fn bench_decode(c: &mut Criterion) {
let arr_bytes = build_byte_array(1000, 32);
c.bench_function("decode/array_1000x32B", |b| {
b.iter(|| {
let mut r = TlvReader::new(black_box(&arr_bytes));
black_box(r.read_value().expect("decode"))
});
});
let arr_uints = build_uint_array(2000);
c.bench_function("decode/array_2000_uint", |b| {
b.iter(|| {
let mut r = TlvReader::new(black_box(&arr_uints));
black_box(r.read_value().expect("decode"))
});
});
let wide = build_wide_struct(500);
c.bench_function("decode/struct_500_uint", |b| {
b.iter(|| {
let mut r = TlvReader::new(black_box(&wide));
black_box(r.read_value().expect("decode"))
});
});
let small = build_small_struct();
c.bench_function("decode/struct_5_uint", |b| {
b.iter(|| {
let mut r = TlvReader::new(black_box(&small));
black_box(r.read_value().expect("decode"))
});
});
let nested = build_nested(30);
c.bench_function("decode/nested_30deep", |b| {
b.iter(|| {
let mut r = TlvReader::new(black_box(&nested));
black_box(r.read_value().expect("decode"))
});
});
let report = build_report_shape(170, 64);
c.bench_function("decode/report_170attr_64B", |b| {
b.iter(|| {
let mut r = TlvReader::new(black_box(&report));
black_box(r.read_value().expect("decode"))
});
});
}
fn build_small_struct() -> Vec<u8> {
build_wide_struct(5)
}
criterion_group!(benches, bench_decode);
criterion_main!(benches);