feat(bench): add safety number & epoch rotation benchmarks, CI workflow

Add safety_number benchmark to crypto_benchmarks.rs, epoch rotation
(propose_self_update + commit) benchmark to mls_operations.rs, expand
add_member group sizes to include 100, and add .github/workflows/bench.yml
that runs Criterion benchmarks and uploads HTML reports as artifacts.
This commit is contained in:
2026-03-04 20:49:42 +01:00
parent 885cce0d7d
commit c401caec60
3 changed files with 93 additions and 3 deletions

54
.github/workflows/bench.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Benchmarks
on:
push:
branches: [main, v2]
pull_request:
branches: [main, v2]
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
bench:
name: Run Criterion benchmarks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-action@stable
- name: Install capnp
run: sudo apt-get update && sudo apt-get install -y capnproto
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-bench-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-bench-
- name: Run benchmarks
run: cargo bench --package quicproquo-core -- --output-format=bencher 2>&1 | tee bench-output.txt
- name: Upload HTML reports
uses: actions/upload-artifact@v4
if: always()
with:
name: criterion-reports
path: target/criterion/
retention-days: 30
- name: Upload raw output
uses: actions/upload-artifact@v4
if: always()
with:
name: bench-output
path: bench-output.txt
retention-days: 30

View File

@@ -8,7 +8,7 @@
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use quicproquo_core::{IdentityKeypair, padding};
use quicproquo_core::{compute_safety_number, IdentityKeypair, padding};
// ── Identity keypair benchmarks ──────────────────────────────────────────────
@@ -127,6 +127,17 @@ fn bench_padding(c: &mut Criterion) {
group.finish();
}
// ── Safety number benchmarks ─────────────────────────────────────────────────
fn bench_safety_number(c: &mut Criterion) {
let key_a = [0x1au8; 32];
let key_b = [0x2bu8; 32];
c.bench_function("safety_number", |b| {
b.iter(|| black_box(compute_safety_number(black_box(&key_a), black_box(&key_b))));
});
}
criterion_group!(
benches,
bench_identity_keygen,
@@ -134,5 +145,6 @@ criterion_group!(
bench_identity_verify,
bench_sealed_sender,
bench_padding,
bench_safety_number,
);
criterion_main!(benches);

View File

@@ -62,8 +62,8 @@ fn bench_group_create(c: &mut Criterion) {
fn bench_add_member(c: &mut Criterion) {
let mut group = c.benchmark_group("mls_add_member");
// Smaller sizes to keep setup time reasonable
for size in [2, 10, 50] {
group.sample_size(10);
for size in [2, 10, 50, 100] {
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
b.iter_batched(
|| {
@@ -83,6 +83,29 @@ fn bench_add_member(c: &mut Criterion) {
group.finish();
}
fn bench_epoch_rotation(c: &mut Criterion) {
let mut group = c.benchmark_group("mls_epoch_rotation");
group.sample_size(10);
for size in [2, 10, 50] {
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, &size| {
b.iter_batched(
|| {
let (mut creator, members) = setup_group(size);
// Propose a self-update to simulate epoch rotation
let proposal = creator.propose_self_update().unwrap();
(creator, members, proposal)
},
|(mut creator, _members, _proposal)| {
// Commit pending proposals (the self-update) to advance the epoch
creator.commit_pending_proposals().unwrap();
},
BatchSize::SmallInput,
);
});
}
group.finish();
}
fn bench_send_message(c: &mut Criterion) {
let mut group = c.benchmark_group("mls_send_message");
for size in [2, 10, 50] {
@@ -127,6 +150,7 @@ criterion_group!(
bench_keygen,
bench_group_create,
bench_add_member,
bench_epoch_rotation,
bench_send_message,
bench_receive_message,
);