From 979d09bb591122711e6579de954e94331bbff835 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Fri, 1 May 2026 05:42:12 +0100 Subject: [PATCH 1/2] Consolidate benchmarks and add wtf-pad-lite bench ready --- crates/chaff-machines/src/wtf_pad_lite.rs | 3 +- crates/chaff-sim/benches/tiktok_undefended.rs | 65 ++++++++++--------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/crates/chaff-machines/src/wtf_pad_lite.rs b/crates/chaff-machines/src/wtf_pad_lite.rs index c3d7545..e4f277a 100644 --- a/crates/chaff-machines/src/wtf_pad_lite.rs +++ b/crates/chaff-machines/src/wtf_pad_lite.rs @@ -17,6 +17,7 @@ use chaff::{ /// /// This defence does not do both burst and gap level padding, has different stop conditions, and a /// different way of sampling distributions. +/// /// # Panics /// /// Shouldn't panic unless modified. @@ -96,5 +97,5 @@ pub fn construct( actions: [FrameworkAction::CancelAll], } } - .expect("preconstructed machine should be valid") + .expect("premade machine with valid distrs was invalid") } diff --git a/crates/chaff-sim/benches/tiktok_undefended.rs b/crates/chaff-sim/benches/tiktok_undefended.rs index ee74307..d755c7e 100644 --- a/crates/chaff-sim/benches/tiktok_undefended.rs +++ b/crates/chaff-sim/benches/tiktok_undefended.rs @@ -3,14 +3,19 @@ #![expect(clippy::unwrap_used)] -use ::chaff::{action::IntegratorAction, event::Event, machine}; +use ::chaff::{ + action::IntegratorAction, + distr::{Distr, DistrKind}, + event::Event, + machine, +}; use chaff_cli::subcommands::simulate; use chaff_datasets::parsers::chaff; -use chaff_machines::constant; +use chaff_machines::{constant, wtf_pad_lite}; use criterion::{Criterion, criterion_group, criterion_main}; -use std::{hint::black_box, path::Path}; +use std::{hint::black_box, path::Path, time::Duration}; -fn constant(c: &mut Criterion) { +fn machines(c: &mut Criterion) { let workspace_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let dataset_dir = workspace_dir .parent() @@ -18,44 +23,30 @@ fn constant(c: &mut Criterion) { .unwrap() .join("data/tik_tok_undefended.chaff"); let dataset = chaff::try_parse(dataset_dir).unwrap(); - let machine = constant::construct(); - c.bench_function("tiktok undefended const", |b| { + let delay_distr: Distr = DistrKind::Normal { + mean: 0.015, + std_dev: 0.05, + } + .try_into() + .unwrap(); + let timeout: Distr = Duration::from_secs_f64(0.4).try_into().unwrap(); + let machine = wtf_pad_lite::construct(delay_distr, timeout); + + c.bench_function("tiktok undefended wtf_pad_lite normal", |b| { b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); }); -} -fn no_op(c: &mut Criterion) { - let workspace_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - let dataset_dir = workspace_dir - .parent() - .and_then(Path::parent) - .unwrap() - .join("data/tik_tok_undefended.chaff"); - let dataset = chaff::try_parse(dataset_dir).unwrap(); - let machine = machine! { - queues: [], - state init {}, - } - .unwrap(); + let machine = constant::construct(); - c.bench_function("tiktok undefended no_op", |b| { + c.bench_function("tiktok undefended const", |b| { b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); }); -} -fn double(c: &mut Criterion) { - let workspace_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - let dataset_dir = workspace_dir - .parent() - .and_then(Path::parent) - .unwrap() - .join("data/tik_tok_undefended.chaff"); - let dataset = chaff::try_parse(dataset_dir).unwrap(); let machine = machine! { queues: [], state double { - action: IntegratorAction::SendDecoy, + actions: [IntegratorAction::SendDecoy], transitions: [ Event::SendNormal => double, ], @@ -66,11 +57,21 @@ fn double(c: &mut Criterion) { c.bench_function("tiktok undefended double", |b| { b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); }); + + let machine = machine! { + queues: [], + state init {}, + } + .unwrap(); + + c.bench_function("tiktok undefended no_op", |b| { + b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); + }); } criterion_group!( name = tiktok_undefended; config = Criterion::default().sample_size(20); - targets = constant, no_op, double + targets = machines ); criterion_main!(tiktok_undefended); From 503903a0bb1e8b9379ae7d74e4043db60c7ffbb4 Mon Sep 17 00:00:00 2001 From: peterc-s Date: Fri, 1 May 2026 12:36:28 +0100 Subject: [PATCH 2/2] Update benchmarking and cli --- crates/chaff-cli/src/main.rs | 20 ++++- crates/chaff-sim/benches/tiktok_undefended.rs | 84 +++++++++++-------- 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/crates/chaff-cli/src/main.rs b/crates/chaff-cli/src/main.rs index 46c57f1..c72decf 100644 --- a/crates/chaff-cli/src/main.rs +++ b/crates/chaff-cli/src/main.rs @@ -5,16 +5,19 @@ #![cfg(not(tarpaulin_include))] use borsh::BorshDeserialize as _; -use std::{fs::File, path::PathBuf}; +use std::{fs::File, path::PathBuf, time::Duration}; use bpaf::Bpaf; -use chaff::machine::Machine; +use chaff::{ + distr::{Distr, DistrKind}, + machine::Machine, +}; use chaff_cli::{ errors::CliError, subcommands::{cap_convert, capture, dataset_convert, dataset_stats, simulate, trace_stats}, utils::parse_dataset, }; -use chaff_machines::constant; +use chaff_machines::wtf_pad_lite; /// Command-line interface options #[derive(Debug, Clone, Bpaf)] @@ -147,11 +150,20 @@ fn run() -> Result<(), CliError> { CliOptions::TraceStats { input } => trace_stats::run(&input), CliOptions::DatasetStats { dataset_type, path } => dataset_stats::run(&dataset_type, &path), CliOptions::Simulate { action, machine } => { + #[expect(clippy::unwrap_used)] let machine = if let Some(path) = machine { let mut file = File::open(path)?; Machine::deserialize_reader(&mut file)? } else { - constant::construct() + // constant::construct() + let delay_distr: Distr = DistrKind::Normal { + mean: 0.015, + std_dev: 0.05, + } + .try_into() + .unwrap(); + let timeout: Distr = Duration::from_secs_f64(1.0).try_into().unwrap(); + wtf_pad_lite::construct(delay_distr, timeout) }; match action { diff --git a/crates/chaff-sim/benches/tiktok_undefended.rs b/crates/chaff-sim/benches/tiktok_undefended.rs index d755c7e..2af3694 100644 --- a/crates/chaff-sim/benches/tiktok_undefended.rs +++ b/crates/chaff-sim/benches/tiktok_undefended.rs @@ -24,49 +24,67 @@ fn machines(c: &mut Criterion) { .join("data/tik_tok_undefended.chaff"); let dataset = chaff::try_parse(dataset_dir).unwrap(); - let delay_distr: Distr = DistrKind::Normal { - mean: 0.015, - std_dev: 0.05, + { + let delay_distr: Distr = DistrKind::Normal { + mean: 0.015, + std_dev: 0.05, + } + .try_into() + .unwrap(); + let timeout: Distr = Duration::from_secs(1).try_into().unwrap(); + let machine = wtf_pad_lite::construct(delay_distr, timeout); + + c.bench_function("tiktok undefended wtf_pad_lite normal", |b| { + b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); + }); } - .try_into() - .unwrap(); - let timeout: Distr = Duration::from_secs_f64(0.4).try_into().unwrap(); - let machine = wtf_pad_lite::construct(delay_distr, timeout); - c.bench_function("tiktok undefended wtf_pad_lite normal", |b| { - b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); - }); + { + let delay_distr: Distr = Duration::from_secs_f64(0.015).try_into().unwrap(); + let timeout: Distr = Duration::from_secs(1).try_into().unwrap(); + let machine = wtf_pad_lite::construct(delay_distr, timeout); - let machine = constant::construct(); + c.bench_function("tiktok undefended wtf_pad_lite constant", |b| { + b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); + }); + } - c.bench_function("tiktok undefended const", |b| { - b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); - }); + { + let machine = constant::construct(); - let machine = machine! { - queues: [], - state double { - actions: [IntegratorAction::SendDecoy], - transitions: [ - Event::SendNormal => double, - ], - }, + c.bench_function("tiktok undefended const", |b| { + b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); + }); } - .unwrap(); - c.bench_function("tiktok undefended double", |b| { - b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); - }); + { + let machine = machine! { + queues: [], + state double { + actions: [IntegratorAction::SendDecoy], + transitions: [ + Event::SendNormal => double, + ], + }, + } + .unwrap(); - let machine = machine! { - queues: [], - state init {}, + c.bench_function("tiktok undefended double", |b| { + b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); + }); } - .unwrap(); - c.bench_function("tiktok undefended no_op", |b| { - b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); - }); + { + let machine = machine! { + queues: [], + state init {}, + } + .unwrap(); + + c.bench_function("tiktok undefended no_op", |b| { + b.iter(|| simulate::run_dataset(black_box(&dataset), &None, black_box(&machine))); + }); + } } criterion_group!(