Skip to content

feat: use criterion for benchmarks #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 11, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion provekit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ edition = "2024"
[dependencies]
rand = { workspace = true }
utils = { workspace = true }
criterion = { workspace = true }
noir-r1cs = { git = "https://github.com/worldfnd/ProveKit", branch = "main" }

[[bench]]
name = "provekit"
name = "prove_verify"
harness = false

[[bin]]
name = "provekit-measure"
path = "src/bin/measure.rs"
16 changes: 16 additions & 0 deletions provekit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ProveKit SHA256 Benchmark

This benchmark code is using the ProveKit of World Foundation(https://github.com/worldfnd/ProveKit).


## Benchmarking

```bash
cargo bench
```

Measure RAM footprint:

```bash
cargo run -r --bin provekit-measure
```
37 changes: 37 additions & 0 deletions provekit/benches/prove_verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
use provekit::{prove, setup, verify};

fn sha256_bench(c: &mut Criterion) {
let mut group = c.benchmark_group("sha256_bench");
group.sample_size(10);

group.bench_function("sha256_bench_prove", |bench| {
bench.iter_batched(
|| {
let _ = setup().unwrap();
},
|| {
prove(2048);
},
BatchSize::SmallInput,
);
});

group.bench_function("sha256_bench_verify", |bench| {
bench.iter_batched(
|| {
let _ = setup().unwrap();
let proof = prove(2048);
proof
},
|proof| {
verify(2048, proof);
},
BatchSize::SmallInput,
);
});
group.finish();
}

criterion_main!(sha256);
criterion_group!(sha256, sha256_bench);
6 changes: 0 additions & 6 deletions provekit/benches/provekit.rs

This file was deleted.

42 changes: 42 additions & 0 deletions provekit/src/bin/measure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use provekit::{CIRCUIT_ROOT, prove, setup};
use utils::bench::{SubMetrics, measure_peak_memory, write_json_submetrics};

fn main() {
let json_file = "sha2_provekit_submetrics.json";

let input_num_bytes = 2048;
let metrics = benchmark_sha2(input_num_bytes);

write_json_submetrics(json_file, &metrics);
}

fn benchmark_sha2(input_num_bytes: usize) -> SubMetrics {
let mut metrics = SubMetrics::new(input_num_bytes);

let (_, peak_memory) = measure_peak_memory(|| setup().unwrap());
metrics.preprocessing_peak_memory = peak_memory;
println!(
"Preprocessing peak memory: {} GB",
peak_memory as f32 / (1024.0 * 1024.0 * 1024.0),
);

// Load the preprocessing files.
let circuit_dir = format!("{}/sha256-bench-{}", CIRCUIT_ROOT, input_num_bytes);
let circuit_path = format!("circuits/target/sha256_bench_{}.json", input_num_bytes);
let prover_toml_path = format!("{}/Prover.toml", circuit_dir);

let proof_scheme_file_bytes = std::fs::read(&circuit_path).unwrap();
let input_map_file_bytes = std::fs::read(&prover_toml_path).unwrap();
metrics.preprocessing_size = proof_scheme_file_bytes.len() + input_map_file_bytes.len();

let (proof, peak_memory) = measure_peak_memory(|| prove(input_num_bytes));
metrics.proving_peak_memory = peak_memory;
metrics.proof_size = proof.whir_r1cs_proof.transcript.len();

println!(
"Proving peak memory: {} GB",
peak_memory as f32 / (1024.0 * 1024.0 * 1024.0),
);

metrics
}
59 changes: 23 additions & 36 deletions provekit/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use noir_r1cs::NoirProofScheme;
use noir_r1cs::{NoirProof, NoirProofScheme};
use rand::RngCore;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::process::Command;
use std::time::Instant;
use utils::bench::{Metrics, benchmark};
use utils::{
bench::{Metrics, benchmark},
metadata::SHA2_INPUTS,
};

pub const INPUT_EXP: [u32; 5] = [8, 9, 10, 11, 12];
pub const TMP_DIR: &str = "tmp";
pub const CIRCUIT_ROOT: &str = "circuits/hash/sha256-provekit";
pub const CSV_OUTPUT: &str = "tmp/provekit_sha256.csv";

/// Generates random input files for hashing benchmarks.
pub fn generate_hash_inputs() -> Result<(), &'static str> {
Expand All @@ -18,9 +19,8 @@ pub fn generate_hash_inputs() -> Result<(), &'static str> {

let mut rng = rand::thread_rng();

for exp in INPUT_EXP {
let size = 1usize << exp;
let bin_path = format!("{}/input_2e{}.bin", input_dir, exp);
for size in SHA2_INPUTS {
let bin_path = format!("{}/input_{}.bin", input_dir, size);

let mut data = vec![0u8; size];
rng.fill_bytes(&mut data);
Expand Down Expand Up @@ -81,10 +81,9 @@ pub fn generate_prover_toml(

/// Sets up Prover.toml files for all circuits.
pub fn setup_circuits() -> Result<(), &'static str> {
for exp in INPUT_EXP {
let size = 1usize << exp;
let input_file = format!("{}/hash-input/input_2e{}.bin", TMP_DIR, exp);
let circuit_dir = format!("{}/sha256-bench-2e{}", CIRCUIT_ROOT, exp);
for size in SHA2_INPUTS {
let input_file = format!("{}/hash-input/input_{}.bin", TMP_DIR, size);
let circuit_dir = format!("{}/sha256-bench-{}", CIRCUIT_ROOT, size);
let toml_path = format!("{}/Prover.toml", circuit_dir);

generate_prover_toml(&toml_path, &input_file, size)?;
Expand All @@ -104,35 +103,23 @@ pub fn setup() -> Result<(), &'static str> {
Ok(())
}

/// Benchmarks provekit with sha256 for all input exponents.
pub fn bench_sha256() {
let inputs: Vec<u32> = INPUT_EXP.to_vec();
pub fn prove(input_num_bytes: usize) -> NoirProof {
let circuit_dir = format!("{}/sha256-bench-{}", CIRCUIT_ROOT, input_num_bytes);
let circuit_path = format!("circuits/target/sha256_bench_{}.json", input_num_bytes);
let prover_toml_path = format!("{}/Prover.toml", circuit_dir);

benchmark(
|input_exp| {
let size = 1usize << input_exp;
let mut metrics = Metrics::new(size);
let proof_scheme = NoirProofScheme::from_file(&circuit_path).unwrap();
let input_map = proof_scheme.read_witness(&prover_toml_path).unwrap();

let circuit_dir = format!("{}/sha256-bench-2e{}", CIRCUIT_ROOT, input_exp);
let circuit_path = format!("circuits/target/sha256_bench_2e{}.json", input_exp);
let prover_toml_path = format!("{}/Prover.toml", circuit_dir);
let proof = proof_scheme.prove(&input_map).unwrap();

let proof_scheme = NoirProofScheme::from_file(&circuit_path).unwrap();
let input_map = proof_scheme.read_witness(&prover_toml_path).unwrap();

let prove_start = Instant::now();
let proof = proof_scheme.prove(&input_map).unwrap();
metrics.proof_duration = prove_start.elapsed();
proof
}

let verify_start = Instant::now();
proof_scheme.verify(&proof).unwrap();
metrics.verify_duration = verify_start.elapsed();
pub fn verify(input_num_bytes: usize, proof: NoirProof) {
let circuit_path = format!("circuits/target/sha256_bench_{}.json", input_num_bytes);

metrics.proof_size = proof.whir_r1cs_proof.transcript.len();
let proof_scheme = NoirProofScheme::from_file(&circuit_path).unwrap();

metrics
},
&inputs,
CSV_OUTPUT,
);
proof_scheme.verify(&proof).unwrap();
}
Loading