ark-curves-cherry-picked/curve-benches/src/macros/field.rs
curve-benches/src/macros/field.rsRaw
1#[macro_export]
2macro_rules! f_bench {
3 // Use this for base fields
4 ($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty, $modname:ident) => {
5 $crate::paste!{
6 pub mod [<_ $modname>] {
7 use super::*;
8 field_common!($f, $f_type);
9 sqrt!($f, $f_type);
10 prime_field!($f, $f_type, $f_repr, $f_repr_type);
11 }
12 $crate::criterion::criterion_group!($modname, [<_ $modname>]::bench_common_field_ops, [<_ $modname>]::bench_sqrt, [<_ $modname>]::bench_prime_field_ops);
13 }
14 };
15 // use this for intermediate fields
16 (extension, $f:ident, $f_type:ty, $modname:ident) => {
17 $crate::paste!{
18 mod [<_ $modname>] {
19 use super::*;
20 field_common!($f, $f_type);
21 sqrt!($f, $f_type);
22 }
23 $crate::criterion::criterion_group!($modname, [<_ $modname>]::bench_common_field_ops, [<_ $modname>]::bench_sqrt);
24 }
25 };
26 // Use this for the full extension field Fqk
27 (target, $f:ident, $f_type:ty, $modname:ident) => {
28 crate::paste! {
29 mod [<_ $modname>] {
30 use super::*;
31 field_common!($f, $f_type);
32 }
33 $crate::criterion::criterion_group!($modname, [<_ $modname>]::bench_common_field_ops);
34 }
35 };
36}
37
38#[macro_export]
39macro_rules! field_common {
40 ($f:ident, $f_type:ty) => {
41 pub fn bench_common_field_ops(c: &mut $crate::criterion::Criterion) {
42 let mut group = c.benchmark_group("Common field operations for ".to_string() + core::stringify!($f));
43 group.bench_function("AddAssign", add_assign);
44 group.bench_function("SubAssign", sub_assign);
45 group.bench_function("Double", double);
46 group.bench_function("Negate", negate);
47 group.bench_function("MulAssign", mul_assign);
48 group.bench_function("Square", square);
49 group.bench_function("Inverse", inverse);
50 group.bench_function("Serialize w/ compression", ser);
51 group.bench_function("Deserialize w/ compression", deser);
52 group.bench_function("Serialize unchecked", ser_unchecked);
53 group.bench_function("Deserialize unchecked", deser_unchecked);
54 }
55
56 fn add_assign(b: &mut $crate::criterion::Bencher) {
57 const SAMPLES: usize = 1000;
58
59 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
60
61 let v: Vec<_> = (0..SAMPLES)
62 .map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
63 .collect();
64
65 let mut count = 0;
66 b.iter(|| {
67 let mut tmp = v[count].0;
68 n_fold!(tmp, v, add_assign, count);
69 count = (count + 1) % SAMPLES;
70 tmp
71 });
72 }
73
74
75 fn sub_assign(b: &mut $crate::criterion::Bencher) {
76 const SAMPLES: usize = 1000;
77
78 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
79
80 let v: Vec<_> = (0..SAMPLES)
81 .map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
82 .collect();
83
84 let mut count = 0;
85 b.iter(|| {
86 let mut tmp = v[count].0;
87 n_fold!(tmp, v, sub_assign, count);
88 count = (count + 1) % SAMPLES;
89 tmp
90 });
91 }
92
93 fn double(b: &mut $crate::criterion::Bencher) {
94 const SAMPLES: usize = 1000;
95
96 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
97
98 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
99
100 let mut count = 0;
101 b.iter(|| {
102 let mut tmp = v[count];
103 n_fold!(tmp, double_in_place);
104 count = (count + 1) % SAMPLES;
105 tmp
106 });
107 }
108
109
110 fn negate(b: &mut $crate::criterion::Bencher) {
111 const SAMPLES: usize = 1000;
112
113 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
114
115 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
116
117 let mut count = 0;
118 b.iter(|| {
119 let mut tmp = v[count];
120 tmp = -tmp;
121 count = (count + 1) % SAMPLES;
122 tmp
123 });
124 }
125
126 fn mul_assign(b: &mut $crate::criterion::Bencher) {
127 const SAMPLES: usize = 1000;
128
129 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
130
131 let v: Vec<_> = (0..SAMPLES)
132 .map(|_| ($f::rand(&mut rng), $f::rand(&mut rng)))
133 .collect();
134
135 let mut count = 0;
136 b.iter(|| {
137 let mut tmp = v[count].0;
138 n_fold!(tmp, v, mul_assign, count);
139 count = (count + 1) % SAMPLES;
140 tmp
141 });
142 }
143
144 fn square(b: &mut $crate::criterion::Bencher) {
145 const SAMPLES: usize = 1000;
146
147 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
148
149 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
150
151 let mut count = 0;
152 b.iter(|| {
153 let mut tmp = v[count];
154 n_fold!(tmp, square_in_place);
155 count = (count + 1) % SAMPLES;
156 tmp
157 });
158 }
159
160
161 fn inverse(b: &mut $crate::criterion::Bencher) {
162 const SAMPLES: usize = 1000;
163
164 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
165
166 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
167
168 let mut count = 0;
169 b.iter(|| {
170 let tmp = v[count].inverse();
171 count = (count + 1) % SAMPLES;
172 tmp
173 });
174 }
175
176
177 fn deser(b: &mut $crate::criterion::Bencher) {
178 use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
179 const SAMPLES: usize = 1000;
180
181 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
182
183 let mut num_bytes = 0;
184 let v: Vec<_> = (0..SAMPLES).flat_map(|_| {
185 let mut bytes = Vec::with_capacity(1000);
186 let tmp = $f::rand(&mut rng);
187 tmp.serialize(&mut bytes).unwrap();
188 num_bytes = bytes.len();
189 bytes
190 }).collect();
191
192 let mut count = 0;
193 b.iter(|| {
194 count = (count + 1) % SAMPLES;
195 let index = count * num_bytes;
196 <$f_type>::deserialize(&v[index..(index + num_bytes)]).unwrap()
197 });
198 }
199
200
201 fn ser(b: &mut $crate::criterion::Bencher) {
202 use ark_serialize::CanonicalSerialize;
203 const SAMPLES: usize = 1000;
204
205 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
206
207 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
208 let mut bytes = Vec::with_capacity(1000);
209
210 let mut count = 0;
211 b.iter(|| {
212 let tmp = v[count];
213 count = (count + 1) % SAMPLES;
214 bytes.clear();
215 tmp.serialize(&mut bytes)
216
217 });
218 }
219
220
221 fn deser_unchecked(b: &mut $crate::criterion::Bencher) {
222 use ark_serialize::{CanonicalSerialize, CanonicalDeserialize};
223 const SAMPLES: usize = 1000;
224
225 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
226
227 let mut num_bytes = 0;
228 let v: Vec<_> = (0..SAMPLES).flat_map(|_| {
229 let mut bytes = Vec::with_capacity(1000);
230 let tmp = $f::rand(&mut rng);
231 tmp.serialize_unchecked(&mut bytes).unwrap();
232 num_bytes = bytes.len();
233 bytes
234 }).collect();
235
236 let mut count = 0;
237 b.iter(|| {
238 count = (count + 1) % SAMPLES;
239 let index = count * num_bytes;
240 <$f_type>::deserialize_unchecked(&v[index..(index + num_bytes)]).unwrap()
241 });
242 }
243
244
245 fn ser_unchecked(b: &mut $crate::criterion::Bencher) {
246 use ark_serialize::CanonicalSerialize;
247 const SAMPLES: usize = 1000;
248
249 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
250
251 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
252 let mut bytes = Vec::with_capacity(1000);
253
254 let mut count = 0;
255 b.iter(|| {
256 let tmp = v[count];
257 count = (count + 1) % SAMPLES;
258 bytes.clear();
259 tmp.serialize_unchecked(&mut bytes)
260
261 });
262 }
263 }
264}
265
266#[macro_export]
267macro_rules! sqrt {
268 ($f:ident, $f_type:ty) => {
269 pub fn bench_sqrt(b: &mut $crate::criterion::Criterion) {
270 const SAMPLES: usize = 1000;
271
272 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
273
274 let v: Vec<$f_type> = (0..SAMPLES)
275 .map(|_| {
276 let mut tmp = $f::rand(&mut rng);
277 tmp.square_in_place();
278 tmp
279 })
280 .collect();
281
282 let mut count = 0;
283 b.bench_function(
284 core::concat!("Square-roots for ", core::stringify!($f)),
285 |_| {
286 count = (count + 1) % SAMPLES;
287 let _ = v[count].sqrt();
288 });
289 }
290 }
291}
292
293#[macro_export]
294macro_rules! prime_field {
295 ($f:ident, $f_type:ty, $f_repr:ident, $f_repr_type:ty) => {
296 pub fn bench_prime_field_ops(c: &mut $crate::criterion::Criterion) {
297 let mut group = c.benchmark_group("Prime field operations for ".to_string() + core::stringify!($f));
298 group.bench_function("AddNoCarry for BigInteger", repr_add_nocarry);
299 group.bench_function("SubNoBorrow for BigInteger", repr_sub_noborrow);
300 group.bench_function("NumBits for BigInteger", repr_num_bits);
301 group.bench_function("MulBy2 for BigInteger", repr_mul2);
302 group.bench_function("DivBy2 for BigInteger", repr_div2);
303 group.bench_function("Into BigInteger", into_repr);
304 group.bench_function("From BigInteger", from_repr);
305 }
306
307 fn repr_add_nocarry(b: &mut $crate::criterion::Bencher) {
308 const SAMPLES: usize = 1000;
309
310 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
311
312 let v: Vec<_> = (0..SAMPLES)
313 .map(|_| {
314 let mut tmp1 = $f_repr::rand(&mut rng);
315 let mut tmp2 = $f_repr::rand(&mut rng);
316 // Shave a few bits off to avoid overflow.
317 for _ in 0..3 {
318 tmp1.div2();
319 tmp2.div2();
320 }
321 (tmp1, tmp2)
322 })
323 .collect();
324
325 let mut count = 0;
326 b.iter(|| {
327 let mut tmp = v[count].0;
328 n_fold!(tmp, v, add_nocarry, count);
329 count = (count + 1) % SAMPLES;
330 tmp
331 });
332 }
333
334 fn repr_sub_noborrow(b: &mut $crate::criterion::Bencher) {
335 const SAMPLES: usize = 1000;
336
337 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
338
339 let v: Vec<_> = (0..SAMPLES)
340 .map(|_| {
341 let tmp1 = $f_repr::rand(&mut rng);
342 let mut tmp2 = tmp1;
343 // Ensure tmp2 is smaller than tmp1.
344 for _ in 0..10 {
345 tmp2.div2();
346 }
347 (tmp1, tmp2)
348 })
349 .collect();
350
351 let mut count = 0;
352 b.iter(|| {
353 let mut tmp = v[count].0;
354 n_fold!(tmp, v, sub_noborrow, count);
355 count = (count + 1) % SAMPLES;
356 tmp;
357 });
358 }
359
360 fn repr_num_bits(b: &mut $crate::criterion::Bencher) {
361 const SAMPLES: usize = 1000;
362
363 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
364
365 let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
366
367 let mut count = 0;
368 b.iter(|| {
369 let tmp = v[count].num_bits();
370 count = (count + 1) % SAMPLES;
371 tmp;
372 });
373 }
374
375 fn repr_mul2(b: &mut $crate::criterion::Bencher) {
376 const SAMPLES: usize = 1000;
377
378 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
379
380 let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
381
382 let mut count = 0;
383 b.iter(|| {
384 let mut tmp = v[count];
385 n_fold!(tmp, mul2);
386 count = (count + 1) % SAMPLES;
387 tmp;
388 });
389 }
390
391 fn repr_div2(b: &mut $crate::criterion::Bencher) {
392 const SAMPLES: usize = 1000;
393
394 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
395
396 let v: Vec<$f_repr_type> = (0..SAMPLES).map(|_| $f_repr::rand(&mut rng)).collect();
397
398 let mut count = 0;
399 b.iter(|| {
400 let mut tmp = v[count];
401 n_fold!(tmp, div2);
402 count = (count + 1) % SAMPLES;
403 tmp;
404 });
405 }
406
407 fn into_repr(b: &mut $crate::criterion::Bencher) {
408 const SAMPLES: usize = 1000;
409
410 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
411
412 let v: Vec<$f_type> = (0..SAMPLES).map(|_| $f::rand(&mut rng)).collect();
413
414 let mut count = 0;
415 b.iter(|| {
416 count = (count + 1) % SAMPLES;
417 v[count].into_repr();
418 });
419 }
420
421 fn from_repr(b: &mut $crate::criterion::Bencher) {
422 const SAMPLES: usize = 1000;
423
424 let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
425
426 let v: Vec<$f_repr_type> = (0..SAMPLES)
427 .map(|_| $f::rand(&mut rng).into_repr())
428 .collect();
429
430 let mut count = 0;
431 b.iter(|| {
432 count = (count + 1) % SAMPLES;
433 $f::from(v[count]);
434 });
435 }
436 }
437}