From db9c63095f1b94ce9be1e96b61414ffb7635642b Mon Sep 17 00:00:00 2001 From: M Alghazwi Date: Tue, 11 Mar 2025 13:09:05 +0100 Subject: [PATCH] add benchmarks --- plonky2/benches/bn254_hash.rs | 107 ++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 plonky2/benches/bn254_hash.rs diff --git a/plonky2/benches/bn254_hash.rs b/plonky2/benches/bn254_hash.rs new file mode 100644 index 00000000..8418676a --- /dev/null +++ b/plonky2/benches/bn254_hash.rs @@ -0,0 +1,107 @@ +use std::any::type_name; +use anyhow::{anyhow, Result}; +use criterion::{criterion_group, criterion_main, Criterion}; +use plonky2::gates::noop::NoopGate; +use plonky2::hash::hash_types::RichField; +use plonky2::iop::witness::PartialWitness; +use plonky2::plonk::circuit_builder::CircuitBuilder; +use plonky2::plonk::circuit_data::CircuitConfig; +use plonky2::plonk::config::{GenericConfig, KeccakGoldilocksConfig, Poseidon2BN254Config, PoseidonGoldilocksConfig}; +use plonky2_field::extension::Extendable; +use plonky2_field::goldilocks_field::GoldilocksField; + +/// Benchmark for building, proving, and verifying the Plonky2 circuit. +fn bench_circuit, const D:usize, C: GenericConfig,>(c: &mut Criterion, circuit_size: usize) -> Result<()>{ + + // Create the circuit configuration + let config = CircuitConfig::standard_recursion_config(); + let mut builder = CircuitBuilder::::new(config); + + let num_dummy_gates = match circuit_size { + 0 => return Err(anyhow!("size must be at least 1")), + 1 => 0, + 2 => 1, + n => (1 << (n - 1)) + 1, + }; + + for _ in 0..num_dummy_gates { + builder.add_gate(NoopGate, vec![]); + } + + // Benchmark Group + let mut group = c.benchmark_group(format!("Circuit Benchmark size {} for hasher: {}", circuit_size, type_name::())); + + // Benchmark the Circuit Building Phase + group.bench_function("Build Circuit", |b| { + b.iter(|| { + let config = CircuitConfig::standard_recursion_config(); + let mut local_builder = CircuitBuilder::::new(config); + for _ in 0..num_dummy_gates { + local_builder.add_gate(NoopGate, vec![]); + } + let _data = local_builder.build::(); + }) + }); + + let data = builder.build::(); + println!("Circuit size (degree bits): {:?}", data.common.degree_bits()); + + // Create a PartialWitness + let mut pw = PartialWitness::new(); + + // Benchmark the Proving Phase + group.bench_function("Prove Circuit", |b| { + b.iter(|| { + let local_pw = pw.clone(); + data.prove(local_pw).expect("Failed to prove circuit") + }) + }); + + // Generate the proof once for verification benchmarking + let proof_with_pis = data.prove(pw.clone()).expect("Failed to prove circuit"); + let verifier_data = data.verifier_data(); + + println!("Proof size: {} bytes", proof_with_pis.to_bytes().len()); + + // Benchmark the Verifying Phase + group.bench_function("Verify Proof", |b| { + b.iter(|| { + verifier_data.verify(proof_with_pis.clone()).expect("Failed to verify proof"); + }) + }); + + group.finish(); + Ok(()) +} + +fn bench_multiple_hashers(c: &mut Criterion){ + const D: usize = 2; + type C1 = PoseidonGoldilocksConfig; + type C2 = KeccakGoldilocksConfig; + type C3 = Poseidon2BN254Config; + type F = GoldilocksField; + + bench_circuit::(c, 10).expect("failed"); + bench_circuit::(c, 10).expect("failed"); + bench_circuit::(c, 10).expect("failed"); + + bench_circuit::(c, 11).expect("failed"); + bench_circuit::(c, 11).expect("failed"); + bench_circuit::(c, 11).expect("failed"); + + bench_circuit::(c, 12).expect("failed"); + bench_circuit::(c, 12).expect("failed"); + bench_circuit::(c, 12).expect("failed"); + + bench_circuit::(c, 13).expect("failed"); + bench_circuit::(c, 13).expect("failed"); + bench_circuit::(c, 13).expect("failed"); +} + +/// Criterion benchmark group +criterion_group!{ + name = prove_verify_benches; + config = Criterion::default().sample_size(10); + targets = bench_multiple_hashers +} +criterion_main!(prove_verify_benches);