diff --git a/Cargo.lock b/Cargo.lock index cebc614..a74e9b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1576,13 +1576,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.24", ] [[package]] @@ -1782,7 +1781,7 @@ dependencies = [ "primitive-types", "proptest", "rand 0.8.5", - "rand 0.9.0", + "rand 0.9.1", "rlp", "ruint-macro", "serde", @@ -2572,6 +2571,10 @@ dependencies = [ "light-poseidon", "num-bigint", "num-traits", + "rand 0.9.1", + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "rln", "serde", "sled", "tiny-keccak", diff --git a/utils/Cargo.toml b/utils/Cargo.toml index 504cf6e..0441dbf 100644 --- a/utils/Cargo.toml +++ b/utils/Cargo.toml @@ -32,6 +32,10 @@ num-traits = "0.2.19" hex-literal = "1.0.0" tiny-keccak = { version = "2.0.2", features = ["keccak"] } criterion = { version = "0.4.0", features = ["html_reports"] } +rand = "0.9.1" +rand_chacha = "0.9.0" +rand_core = "0.9.3" +rln = { path = "../rln", default-features = false } [features] default = [] diff --git a/utils/benches/poseidon_benchmark.rs b/utils/benches/poseidon_benchmark.rs index b2ee6ad..46040a4 100644 --- a/utils/benches/poseidon_benchmark.rs +++ b/utils/benches/poseidon_benchmark.rs @@ -5,6 +5,10 @@ use criterion::{ use light_poseidon::{ PoseidonHasher as LPoseidonHasher, PoseidonParameters as LPoseidonParameters, }; +use rand::RngCore; +use rand_chacha::ChaCha8Rng; +use rand_core::SeedableRng; +use rln::utils::bytes_le_to_fr; use zerokit_utils::{Poseidon, RoundParameters}; const ROUND_PARAMS: [(usize, usize, usize, usize); 8] = [ @@ -18,109 +22,81 @@ const ROUND_PARAMS: [(usize, usize, usize, usize); 8] = [ (9, 8, 63, 0), ]; -fn make_values(size: u32) -> Vec<[Fr; 1]> { - (0..size).map(|i| [Fr::from(i)]).collect() +struct U256Stream { + rng: ChaCha8Rng, +} +impl U256Stream { + fn seeded_stream(seed: u64) -> Self { + let rng = ChaCha8Rng::seed_from_u64(seed); + Self { rng } + } +} + +impl Iterator for U256Stream { + type Item = [u8; 32]; + + fn next(&mut self) -> Option { + let mut res = [0; 32]; + self.rng.fill_bytes(&mut res); + Some(res) + } } pub fn poseidon_benchmark(c: &mut Criterion) { let hasher = Poseidon::::from(&ROUND_PARAMS); let mut group = c.benchmark_group("poseidon Fr"); - // pull out the _actual_ parameters used by the benchmark. - // This is a potential smell: It doesn't feel "clean" to do it this way, however, I can't see a - // clear way to get an equivilent parameter set without non-trivial work to the ift poseidon - // implimentation - let RoundParameters { - t, - n_rounds_full, - n_rounds_partial, - skip_matrices: _, - ark_consts, - mds, - } = hasher.select_params(&[Fr::from(1)]).unwrap(); - // group.measurement_time(std::time::Duration::from_secs(30)); - for size in [10u32, 100, 1000].iter() { + for size in [1u32, 2].iter() { group.throughput(Throughput::Elements(*size as u64)); + let vals = U256Stream::seeded_stream(*size as u64) + .take(*size as usize) + .map(|b| bytes_le_to_fr(&b).0) + .collect::>(); + let RoundParameters { + t, + n_rounds_full, + n_rounds_partial, + skip_matrices: _, + ark_consts, + mds, + } = hasher.select_params(&vals).unwrap(); - group.bench_with_input( - BenchmarkId::new("Array hash light", size), - size, - |b, &size| { - b.iter_batched( - // setup - || { - // this needs to be done here due to move/copy/etc issues. - let l_params = LPoseidonParameters { - ark: ark_consts.clone(), - mds: mds.clone(), - full_rounds: *n_rounds_full, - partial_rounds: *n_rounds_partial, - width: *t, - alpha: 5, - }; - let vals = make_values(size); - let light_hasher = light_poseidon::Poseidon::::new(l_params); - (vals, light_hasher) - }, - // Actual benchmark - |(values, mut light_hasher)| { - for v in values.iter() { - let _ = light_hasher.hash(black_box(&v[..])); - } - }, - BatchSize::SmallInput, - ) - }, - ); - group.bench_with_input( - BenchmarkId::new("Array hash ift", size), - size, - |b, &size| { - b.iter_batched( - // setup - || make_values(size), - // Actual benchmark - |values| { - for v in values.iter() { - let _ = hasher.hash(black_box(&v[..])); - } - }, - BatchSize::SmallInput, - ) - }, - ); - group.bench_with_input( - BenchmarkId::new("Array hash light_circom", size), - size, - |b, &size| { - b.iter_batched( - // setup - || { - let light_hasher_circom = - light_poseidon::Poseidon::::new_circom(1).unwrap(); - (light_hasher_circom, make_values(size)) - }, - // Actual benchmark - |(mut light_hasher_circom, values)| { - for v in values.iter() { - let _ = light_hasher_circom.hash(black_box(&v[..])); - } - }, - BatchSize::SmallInput, - ) - }, - ); + group.bench_function(BenchmarkId::new("Array hash light", size), |b| { + b.iter_batched( + // setup + || { + // this needs to be done here due to move/copy/etc issues. + let l_params = LPoseidonParameters { + ark: ark_consts.clone(), + mds: mds.clone(), + full_rounds: *n_rounds_full, + partial_rounds: *n_rounds_partial, + width: *t, + alpha: 5, + }; + + light_poseidon::Poseidon::::new(l_params) + }, + // Actual benchmark + |mut light_hasher| black_box(light_hasher.hash(&vals)), + BatchSize::SmallInput, + ) + }); + group.bench_function(BenchmarkId::new("Array hash ift", size), |b| { + b.iter(|| black_box(hasher.hash(&vals))) + }); + group.bench_function(BenchmarkId::new("Array hash light_circom", size), |b| { + b.iter_batched( + // setup + || light_poseidon::Poseidon::::new_circom(*size as usize).unwrap(), + // Actual benchmark + |mut light_hasher_circom| black_box(light_hasher_circom.hash(&vals)), + BatchSize::SmallInput, + ) + }); } - // Benchmark single hash operation separately - group.bench_function("Single hash", |b| { - let input = [Fr::from(u64::MAX)]; - b.iter(|| { - let _ = hasher.hash(black_box(&input[..])); - }) - }); - group.finish(); }