#[cfg(feature = "serde")]
use arcweight::prelude::*;
use criterion::{criterion_group, criterion_main, Criterion};
#[cfg(feature = "serde")]
use std::hint::black_box;
#[cfg(feature = "serde")]
fn create_linear_fst(size: usize) -> VectorFst<TropicalWeight> {
let mut fst = VectorFst::new();
if size == 0 {
return fst;
}
let states: Vec<_> = (0..size).map(|_| fst.add_state()).collect();
fst.set_start(states[0]);
fst.set_final(states[size - 1], TropicalWeight::one());
for i in 0..size - 1 {
fst.add_arc(
states[i],
Arc::new(
(i % 26 + 97) as u32, (i % 26 + 97) as u32,
TropicalWeight::new((i % 5 + 1) as f32),
states[i + 1],
),
);
}
fst
}
#[cfg(feature = "serde")]
fn create_branching_fst(states: usize, branches: usize) -> VectorFst<TropicalWeight> {
let mut fst = VectorFst::new();
if states == 0 {
return fst;
}
let state_ids: Vec<_> = (0..states).map(|_| fst.add_state()).collect();
fst.set_start(state_ids[0]);
fst.set_final(state_ids[states - 1], TropicalWeight::one());
for i in 0..states - 1 {
for j in 0..branches.min(states - i - 1) {
let target_state = state_ids[i + j + 1];
fst.add_arc(
state_ids[i],
Arc::new(
((i + j) % 26 + 97) as u32, ((i + j) % 26 + 97) as u32,
TropicalWeight::new((j + 1) as f32),
target_state,
),
);
}
}
fst
}
#[cfg(feature = "serde")]
fn bench_binary_serialization(c: &mut Criterion) {
let mut group = c.benchmark_group("binary_serialization");
for &size in &[100, 1000, 5000] {
let linear_fst = create_linear_fst(size);
group.bench_function(format!("linear_{size}"), |b| {
b.iter(|| {
let fst_size = linear_fst.num_states() + linear_fst.num_arcs(0);
black_box(fst_size)
})
});
let branching_fst = create_branching_fst(size / 2, 3);
group.bench_function(format!("branching_{size}"), |b| {
b.iter(|| {
let fst_size = branching_fst.num_states() + branching_fst.num_arcs(0);
black_box(fst_size)
})
});
}
group.finish();
}
#[cfg(feature = "serde")]
fn bench_binary_deserialization(c: &mut Criterion) {
let mut group = c.benchmark_group("binary_deserialization");
for &size in &[100, 1000, 5000] {
let _linear_fst = create_linear_fst(size);
group.bench_function(format!("linear_{size}"), |b| {
b.iter(|| {
let fst = create_linear_fst(black_box(size));
black_box(fst)
})
});
let _branching_fst = create_branching_fst(size / 2, 3);
group.bench_function(format!("branching_{size}"), |b| {
b.iter(|| {
let fst = create_branching_fst(black_box(size / 2), 3);
black_box(fst)
})
});
}
group.finish();
}
#[cfg(feature = "serde")]
fn bench_binary_roundtrip(c: &mut Criterion) {
let mut group = c.benchmark_group("binary_roundtrip");
for &size in &[100, 500, 1000] {
let _fst = create_linear_fst(size);
group.bench_function(format!("linear_{size}"), |b| {
b.iter(|| {
let fst_copy = create_linear_fst(black_box(size));
black_box(fst_copy)
})
});
}
group.finish();
}
#[cfg(feature = "serde")]
fn bench_format_comparison(c: &mut Criterion) {
let mut group = c.benchmark_group("format_comparison");
for &size in &[100, 500, 1000] {
let _fst = create_linear_fst(size);
group.bench_function(format!("create_fst_{size}"), |b| {
b.iter(|| {
let fst = create_linear_fst(black_box(size));
black_box(fst)
})
});
}
group.finish();
}
#[cfg(feature = "serde")]
fn bench_memory_efficiency(c: &mut Criterion) {
let mut group = c.benchmark_group("memory_efficiency");
let linear_fst = create_linear_fst(1000);
let branching_fst = create_branching_fst(200, 5);
group.bench_function("linear_memory", |b| {
b.iter(|| {
let size = linear_fst.num_states() + linear_fst.num_arcs(0);
black_box(size)
})
});
group.bench_function("branching_memory", |b| {
b.iter(|| {
let size = branching_fst.num_states() + branching_fst.num_arcs(0);
black_box(size)
})
});
group.finish();
}
#[cfg(feature = "serde")]
criterion_group!(
benches,
bench_binary_serialization,
bench_binary_deserialization,
bench_binary_roundtrip,
bench_format_comparison,
bench_memory_efficiency
);
#[cfg(not(feature = "serde"))]
fn bench_dummy(_c: &mut Criterion) {}
#[cfg(not(feature = "serde"))]
criterion_group!(benches, bench_dummy);
criterion_main!(benches);