ark-r1cs-std/benches/bench.rs
benches/bench.rsRaw
1use ark_ff::PrimeField;
2use ark_r1cs_std::{
3 alloc::AllocVar,
4 eq::EqGadget,
5 fields::{nonnative::NonNativeFieldVar, FieldVar},
6};
7use ark_relations::{
8 ns,
9 r1cs::{ConstraintSystem, ConstraintSystemRef, OptimizationGoal},
10};
11use ark_std::rand::RngCore;
12
13const NUM_REPETITIONS: usize = 1;
14
15fn get_density<BaseField: PrimeField>(cs: &ConstraintSystemRef<BaseField>) -> usize {
16 match cs {
17 ConstraintSystemRef::None => panic!("Constraint system is none."),
18 ConstraintSystemRef::CS(r) => {
19 let mut cs_bak = r.borrow().clone();
20
21 cs_bak.finalize();
22 let matrices = cs_bak.to_matrices().unwrap();
23
24 matrices.a_num_non_zero + matrices.b_num_non_zero + matrices.c_num_non_zero
25 },
26 }
27}
28
29fn allocation<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
30 cs: ConstraintSystemRef<BaseField>,
31 rng: &mut R,
32) -> (usize, usize) {
33 let a_native = TargetField::rand(rng);
34
35 let constraints_before = cs.num_constraints();
36 let nonzeros_before = get_density(&cs);
37
38 // There will be a check that ensures it has the reasonable number of bits
39 let _ = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "alloc a"), || {
40 Ok(a_native)
41 })
42 .unwrap();
43
44 let constraints_after = cs.num_constraints();
45 let nonzeros_after = get_density(&cs);
46
47 return (
48 constraints_after - constraints_before,
49 nonzeros_after - nonzeros_before,
50 );
51}
52
53fn addition<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
54 cs: ConstraintSystemRef<BaseField>,
55 rng: &mut R,
56) -> (usize, usize) {
57 let a_native = TargetField::rand(rng);
58 let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "alloc a"), || {
59 Ok(a_native)
60 })
61 .unwrap();
62
63 let b_native = TargetField::rand(rng);
64 let b = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "alloc b"), || {
65 Ok(b_native)
66 })
67 .unwrap();
68
69 let constraints_before = cs.num_constraints();
70 let nonzeros_before = get_density(&cs);
71
72 let _ = &a + &b;
73
74 let constraints_after = cs.num_constraints();
75 let nonzeros_after = get_density(&cs);
76
77 return (
78 constraints_after - constraints_before,
79 nonzeros_after - nonzeros_before,
80 );
81}
82
83fn equality<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
84 cs: ConstraintSystemRef<BaseField>,
85 rng: &mut R,
86) -> (usize, usize) {
87 let a_native = TargetField::rand(rng);
88 let a1 = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "alloc a1"), || {
89 Ok(a_native)
90 })
91 .unwrap();
92 let a2 = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "alloc a2"), || {
93 Ok(a_native)
94 })
95 .unwrap();
96
97 let constraints_before = cs.num_constraints();
98 let nonzeros_before = get_density(&cs);
99
100 a1.enforce_equal(&a2).unwrap();
101
102 let constraints_after = cs.num_constraints();
103 let nonzeros_after = get_density(&cs);
104
105 return (
106 constraints_after - constraints_before,
107 nonzeros_after - nonzeros_before,
108 );
109}
110
111fn multiplication<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
112 cs: ConstraintSystemRef<BaseField>,
113 rng: &mut R,
114) -> (usize, usize) {
115 let a_native = TargetField::rand(rng);
116 let a = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "initial a"), || {
117 Ok(a_native)
118 })
119 .unwrap();
120
121 let b_native = TargetField::rand(rng);
122 let b = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "initial b"), || {
123 Ok(b_native)
124 })
125 .unwrap();
126
127 let constraints_before = cs.num_constraints();
128 let nonzeros_before = get_density(&cs);
129
130 let _ = &a * &b;
131
132 let constraints_after = cs.num_constraints();
133 let nonzeros_after = get_density(&cs);
134
135 return (
136 constraints_after - constraints_before,
137 nonzeros_after - nonzeros_before,
138 );
139}
140
141fn inverse<TargetField: PrimeField, BaseField: PrimeField, R: RngCore>(
142 cs: ConstraintSystemRef<BaseField>,
143 rng: &mut R,
144) -> (usize, usize) {
145 let num_native = TargetField::rand(rng);
146 let num = NonNativeFieldVar::<TargetField, BaseField>::new_witness(ns!(cs, "alloc"), || {
147 Ok(num_native)
148 })
149 .unwrap();
150
151 let constraints_before = cs.num_constraints();
152 let nonzeros_before = get_density(&cs);
153
154 let _ = num.inverse().unwrap();
155
156 let constraints_after = cs.num_constraints();
157 let nonzeros_after = get_density(&cs);
158
159 return (
160 constraints_after - constraints_before,
161 nonzeros_after - nonzeros_before,
162 );
163}
164
165macro_rules! nonnative_bench_individual {
166 ($bench_method:ident, $bench_name:ident, $bench_target_field:ty, $bench_base_field:ty) => {
167 let rng = &mut ark_std::test_rng();
168 let mut num_constraints = 0;
169 let mut num_nonzeros = 0;
170 for _ in 0..NUM_REPETITIONS {
171 let cs_sys = ConstraintSystem::<$bench_base_field>::new();
172 let cs = ConstraintSystemRef::new(cs_sys);
173 cs.set_optimization_goal(OptimizationGoal::Constraints);
174
175 let (cur_constraints, cur_nonzeros) =
176 $bench_method::<$bench_target_field, $bench_base_field, _>(cs.clone(), rng);
177
178 num_constraints += cur_constraints;
179 num_nonzeros += cur_nonzeros;
180
181 assert!(cs.is_satisfied().unwrap());
182 }
183 let average_constraints = num_constraints / NUM_REPETITIONS;
184 let average_nonzeros = num_nonzeros / NUM_REPETITIONS;
185 println!(
186 "{} takes: {} constraints, {} non-zeros",
187 stringify!($bench_method),
188 average_constraints,
189 average_nonzeros,
190 );
191 };
192}
193
194macro_rules! nonnative_bench {
195 ($bench_name:ident, $bench_target_field:ty, $bench_base_field:ty) => {
196 println!(
197 "For {} to simulate {}",
198 stringify!($bench_base_field),
199 stringify!($bench_target_field),
200 );
201 nonnative_bench_individual!(
202 allocation,
203 $bench_name,
204 $bench_target_field,
205 $bench_base_field
206 );
207 nonnative_bench_individual!(
208 addition,
209 $bench_name,
210 $bench_target_field,
211 $bench_base_field
212 );
213 nonnative_bench_individual!(
214 multiplication,
215 $bench_name,
216 $bench_target_field,
217 $bench_base_field
218 );
219 nonnative_bench_individual!(
220 equality,
221 $bench_name,
222 $bench_target_field,
223 $bench_base_field
224 );
225 nonnative_bench_individual!(inverse, $bench_name, $bench_target_field, $bench_base_field);
226 println!("----------------------")
227 };
228}
229
230fn main() {
231 nonnative_bench!(MNT46Small, ark_mnt4_298::Fr, ark_mnt6_298::Fr);
232 nonnative_bench!(MNT64Small, ark_mnt6_298::Fr, ark_mnt4_298::Fr);
233 nonnative_bench!(MNT46Big, ark_mnt4_753::Fr, ark_mnt6_753::Fr);
234 nonnative_bench!(MNT64Big, ark_mnt6_753::Fr, ark_mnt4_753::Fr);
235 nonnative_bench!(BLS12MNT4Small, ark_bls12_381::Fr, ark_mnt4_298::Fr);
236 nonnative_bench!(BLS12, ark_bls12_381::Fq, ark_bls12_381::Fr);
237 nonnative_bench!(MNT6BigMNT4Small, ark_mnt6_753::Fr, ark_mnt4_298::Fr);
238}