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