arcweight 0.3.0

A high-performance, modular library for weighted finite state transducers with comprehensive examples and benchmarks
Documentation
//! Parallel vs sequential composition benchmarks
//! Measures speedup from parallel composition implementation

use arcweight::prelude::*;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use std::hint::black_box;
use std::time::Duration;

fn create_dense_fst(states: usize, arcs_per_state: usize) -> VectorFst<TropicalWeight> {
    let mut fst = VectorFst::new();
    let mut state_ids = Vec::with_capacity(states);

    for _ in 0..states {
        state_ids.push(fst.add_state());
    }

    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..arcs_per_state {
            fst.add_arc(
                state_ids[i],
                Arc::new(
                    (j % 10 + 1) as u32, // Labels 1-10
                    (j % 10 + 1) as u32,
                    TropicalWeight::new((j as f32) * 0.1),
                    state_ids[i + 1],
                ),
            );
        }
    }

    fst
}

pub fn bench_composition_scaling(c: &mut Criterion) {
    let mut group = c.benchmark_group("composition_scaling");
    group.measurement_time(Duration::from_secs(10));

    // Test composition with increasing FST sizes
    for states in [50, 100, 200, 500].iter() {
        let fst1 = create_dense_fst(*states, 5);
        let fst2 = create_dense_fst(*states, 5);

        group.bench_with_input(BenchmarkId::new("sequential", states), states, |b, _| {
            b.iter(|| {
                let result: VectorFst<TropicalWeight> =
                    compose_default(black_box(&fst1), black_box(&fst2)).unwrap();
                black_box(result);
            })
        });

        // Parallel composition benchmark placeholder
        // Will compare against sequential after parallel implementation
    }

    group.finish();
}

pub fn bench_composition_arc_density(c: &mut Criterion) {
    let mut group = c.benchmark_group("composition_arc_density");
    group.measurement_time(Duration::from_secs(10));

    // Fixed state count, varying arc density
    let states = 100;
    for arcs_per_state in [2, 5, 10, 20].iter() {
        let fst1 = create_dense_fst(states, *arcs_per_state);
        let fst2 = create_dense_fst(states, *arcs_per_state);

        group.bench_with_input(
            BenchmarkId::new("arcs_per_state", arcs_per_state),
            arcs_per_state,
            |b, _| {
                b.iter(|| {
                    let result: VectorFst<TropicalWeight> =
                        compose_default(black_box(&fst1), black_box(&fst2)).unwrap();
                    black_box(result);
                })
            },
        );
    }

    group.finish();
}

pub fn bench_composition_chain(c: &mut Criterion) {
    let mut group = c.benchmark_group("composition_chain");
    group.measurement_time(Duration::from_secs(10));

    let fst1 = create_dense_fst(50, 5);
    let fst2 = create_dense_fst(50, 5);
    let fst3 = create_dense_fst(50, 5);

    group.bench_function("two_way", |b| {
        b.iter(|| {
            let result: VectorFst<TropicalWeight> =
                compose_default(black_box(&fst1), black_box(&fst2)).unwrap();
            black_box(result);
        })
    });

    group.bench_function("three_way", |b| {
        b.iter(|| {
            let intermediate: VectorFst<TropicalWeight> =
                compose_default(black_box(&fst1), black_box(&fst2)).unwrap();
            let result: VectorFst<TropicalWeight> =
                compose_default(black_box(&intermediate), black_box(&fst3)).unwrap();
            black_box(result);
        })
    });

    group.finish();
}

criterion_group!(
    benches,
    bench_composition_scaling,
    bench_composition_arc_density,
    bench_composition_chain
);
criterion_main!(benches);