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::{emulated_fp::EmulatedFpVar, 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<TargetF: PrimeField, BaseField: PrimeField, R: RngCore>(
30 cs: ConstraintSystemRef<BaseField>,
31 rng: &mut R,
32) -> (usize, usize) {
33 let a_native = TargetF::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 _ = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "alloc a"), || Ok(a_native))
40 .unwrap();
41
42 let constraints_after = cs.num_constraints();
43 let nonzeros_after = get_density(&cs);
44
45 return (
46 constraints_after - constraints_before,
47 nonzeros_after - nonzeros_before,
48 );
49}
50
51fn addition<TargetF: PrimeField, BaseField: PrimeField, R: RngCore>(
52 cs: ConstraintSystemRef<BaseField>,
53 rng: &mut R,
54) -> (usize, usize) {
55 let a_native = TargetF::rand(rng);
56 let a = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "alloc a"), || Ok(a_native))
57 .unwrap();
58
59 let b_native = TargetF::rand(rng);
60 let b = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "alloc b"), || Ok(b_native))
61 .unwrap();
62
63 let constraints_before = cs.num_constraints();
64 let nonzeros_before = get_density(&cs);
65
66 let _ = &a + &b;
67
68 let constraints_after = cs.num_constraints();
69 let nonzeros_after = get_density(&cs);
70
71 return (
72 constraints_after - constraints_before,
73 nonzeros_after - nonzeros_before,
74 );
75}
76
77fn equality<TargetF: PrimeField, BaseField: PrimeField, R: RngCore>(
78 cs: ConstraintSystemRef<BaseField>,
79 rng: &mut R,
80) -> (usize, usize) {
81 let a_native = TargetF::rand(rng);
82 let a1 = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "alloc a1"), || Ok(a_native))
83 .unwrap();
84 let a2 = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "alloc a2"), || Ok(a_native))
85 .unwrap();
86
87 let constraints_before = cs.num_constraints();
88 let nonzeros_before = get_density(&cs);
89
90 a1.enforce_equal(&a2).unwrap();
91
92 let constraints_after = cs.num_constraints();
93 let nonzeros_after = get_density(&cs);
94
95 return (
96 constraints_after - constraints_before,
97 nonzeros_after - nonzeros_before,
98 );
99}
100
101fn multiplication<TargetF: PrimeField, BaseField: PrimeField, R: RngCore>(
102 cs: ConstraintSystemRef<BaseField>,
103 rng: &mut R,
104) -> (usize, usize) {
105 let a_native = TargetF::rand(rng);
106 let a = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "initial a"), || Ok(a_native))
107 .unwrap();
108
109 let b_native = TargetF::rand(rng);
110 let b = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "initial b"), || Ok(b_native))
111 .unwrap();
112
113 let constraints_before = cs.num_constraints();
114 let nonzeros_before = get_density(&cs);
115
116 let _ = &a * &b;
117
118 let constraints_after = cs.num_constraints();
119 let nonzeros_after = get_density(&cs);
120
121 return (
122 constraints_after - constraints_before,
123 nonzeros_after - nonzeros_before,
124 );
125}
126
127fn inverse<TargetF: PrimeField, BaseField: PrimeField, R: RngCore>(
128 cs: ConstraintSystemRef<BaseField>,
129 rng: &mut R,
130) -> (usize, usize) {
131 let num_native = TargetF::rand(rng);
132 let num = EmulatedFpVar::<TargetF, BaseField>::new_witness(ns!(cs, "alloc"), || Ok(num_native))
133 .unwrap();
134
135 let constraints_before = cs.num_constraints();
136 let nonzeros_before = get_density(&cs);
137
138 let _ = num.inverse().unwrap();
139
140 let constraints_after = cs.num_constraints();
141 let nonzeros_after = get_density(&cs);
142
143 return (
144 constraints_after - constraints_before,
145 nonzeros_after - nonzeros_before,
146 );
147}
148
149macro_rules! nonnative_bench_individual {
150 ($bench_method:ident, $bench_name:ident, $bench_target_field:ty, $bench_base_field:ty) => {
151 let rng = &mut ark_std::test_rng();
152 let mut num_constraints = 0;
153 let mut num_nonzeros = 0;
154 for _ in 0..NUM_REPETITIONS {
155 let cs_sys = ConstraintSystem::<$bench_base_field>::new();
156 let cs = ConstraintSystemRef::new(cs_sys);
157 cs.set_optimization_goal(OptimizationGoal::Constraints);
158
159 let (cur_constraints, cur_nonzeros) =
160 $bench_method::<$bench_target_field, $bench_base_field, _>(cs.clone(), rng);
161
162 num_constraints += cur_constraints;
163 num_nonzeros += cur_nonzeros;
164
165 assert!(cs.is_satisfied().unwrap());
166 }
167 let average_constraints = num_constraints / NUM_REPETITIONS;
168 let average_nonzeros = num_nonzeros / NUM_REPETITIONS;
169 println!(
170 "{} takes: {} constraints, {} non-zeros",
171 stringify!($bench_method),
172 average_constraints,
173 average_nonzeros,
174 );
175 };
176}
177
178macro_rules! nonnative_bench {
179 ($bench_name:ident, $bench_target_field:ty, $bench_base_field:ty) => {
180 println!(
181 "For {} to simulate {}",
182 stringify!($bench_base_field),
183 stringify!($bench_target_field),
184 );
185 nonnative_bench_individual!(
186 allocation,
187 $bench_name,
188 $bench_target_field,
189 $bench_base_field
190 );
191 nonnative_bench_individual!(
192 addition,
193 $bench_name,
194 $bench_target_field,
195 $bench_base_field
196 );
197 nonnative_bench_individual!(
198 multiplication,
199 $bench_name,
200 $bench_target_field,
201 $bench_base_field
202 );
203 nonnative_bench_individual!(
204 equality,
205 $bench_name,
206 $bench_target_field,
207 $bench_base_field
208 );
209 nonnative_bench_individual!(inverse, $bench_name, $bench_target_field, $bench_base_field);
210 println!("----------------------")
211 };
212}
213
214fn main() {
215 nonnative_bench!(MNT46Small, ark_mnt4_298::Fr, ark_mnt6_298::Fr);
216 nonnative_bench!(MNT64Small, ark_mnt6_298::Fr, ark_mnt4_298::Fr);
217 nonnative_bench!(MNT46Big, ark_mnt4_753::Fr, ark_mnt6_753::Fr);
218 nonnative_bench!(MNT64Big, ark_mnt6_753::Fr, ark_mnt4_753::Fr);
219 nonnative_bench!(BLS12MNT4Small, ark_bls12_381::Fr, ark_mnt4_298::Fr);
220 nonnative_bench!(BLS12, ark_bls12_381::Fq, ark_bls12_381::Fr);
221 nonnative_bench!(MNT6BigMNT4Small, ark_mnt6_753::Fr, ark_mnt4_298::Fr);
222}