Skip to content

Commit 76685c9

Browse files
authored
primefield: add bench_field! macro; use in bp256 (#1587)
This adds a macro to the `primefield::dev` macro for writing field benchmarks, and uses them to write a basic set of benchmarks for the `FieldElement` and `Scalar` types in `bp256`. We should roll these out to the other crates that currently lack benchmarks, but first it would be nice to augment them with ones for point operations, namely scalar multiplication.
1 parent 8006f06 commit 76685c9

File tree

5 files changed

+116
-0
lines changed

5 files changed

+116
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bp256/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ primefield = { version = "0.14.0-rc.3", optional = true }
2222
primeorder = { version = "0.14.0-rc.3", optional = true }
2323
sha2 = { version = "0.11.0-rc.3", optional = true, default-features = false }
2424

25+
[dev-dependencies]
26+
criterion = "0.7"
27+
2528
[features]
2629
default = ["pkcs8", "std"]
2730
alloc = ["ecdsa?/alloc", "elliptic-curve/alloc", "primeorder?/alloc"]
@@ -35,6 +38,16 @@ pkcs8 = ["ecdsa/pkcs8", "elliptic-curve/pkcs8"]
3538
serde = ["ecdsa/serde", "elliptic-curve/serde"]
3639
sha256 = ["ecdsa/digest", "ecdsa/hazmat", "sha2"]
3740

41+
[[bench]]
42+
name = "field"
43+
harness = false
44+
required-features = ["arithmetic"]
45+
46+
[[bench]]
47+
name = "scalar"
48+
harness = false
49+
required-features = ["arithmetic"]
50+
3851
[package.metadata.docs.rs]
3952
all-features = true
4053

bp256/benches/field.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//! bp256 `FieldElement` benchmarks
2+
3+
use bp256::BrainpoolP256r1;
4+
use criterion::{Criterion, criterion_group, criterion_main};
5+
use primeorder::PrimeCurveParams;
6+
7+
type FieldElement = <BrainpoolP256r1 as PrimeCurveParams>::FieldElement;
8+
9+
const FE_A: FieldElement = FieldElement::from_hex_vartime(
10+
"8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
11+
);
12+
const FE_B: FieldElement = FieldElement::from_hex_vartime(
13+
"547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
14+
);
15+
16+
primefield::bench_field!(bench_field_element, "FieldElement", FE_A, FE_B);
17+
criterion_group!(benches, bench_field_element);
18+
criterion_main!(benches);

bp256/benches/scalar.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//! bp256 `Scalar` benchmarks
2+
3+
use bp256::Scalar;
4+
use criterion::{Criterion, criterion_group, criterion_main};
5+
6+
const SCALAR_A: Scalar =
7+
Scalar::from_hex_vartime("9bb0d8b72602b70dd5cfed99607a2e2c021dd0fe3b3af842df02c06f8c1a0f4e");
8+
const SCALAR_B: Scalar =
9+
Scalar::from_hex_vartime("6494152e2b6c34768296d2ea0e984f89a77f0d7399b70f2e29789128423a9bea");
10+
11+
primefield::bench_field!(bench_scalar, "Scalar", SCALAR_A, SCALAR_B);
12+
criterion_group!(benches, bench_scalar);
13+
criterion_main!(benches);

primefield/src/dev.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,74 @@
1+
/// Write a series of `criterion`-based benchmarks for a field implementation.
2+
#[macro_export]
3+
macro_rules! bench_field {
4+
{ $name:ident, $desc:expr, $fe_a:expr, $fe_b:expr } => {
5+
fn bench_add<M: ::criterion::measurement::Measurement>(
6+
group: &mut ::criterion::BenchmarkGroup<'_, M>,
7+
) {
8+
let x = core::hint::black_box($fe_a);
9+
let y = core::hint::black_box($fe_b);
10+
group.bench_function("add", |b| b.iter(|| x + y));
11+
}
12+
13+
fn bench_sub<M: ::criterion::measurement::Measurement>(
14+
group: &mut ::criterion::BenchmarkGroup<'_, M>,
15+
) {
16+
let x = core::hint::black_box($fe_a);
17+
let y = core::hint::black_box($fe_b);
18+
group.bench_function("sub", |b| b.iter(|| x - y));
19+
}
20+
21+
fn bench_mul<M: ::criterion::measurement::Measurement>(
22+
group: &mut ::criterion::BenchmarkGroup<'_, M>,
23+
) {
24+
let x = core::hint::black_box($fe_a);
25+
let y = core::hint::black_box($fe_b);
26+
group.bench_function("mul", |b| b.iter(|| x * y));
27+
}
28+
29+
fn bench_neg<M: ::criterion::measurement::Measurement>(
30+
group: &mut ::criterion::BenchmarkGroup<'_, M>,
31+
) {
32+
let x = core::hint::black_box($fe_a);
33+
group.bench_function("neg", |b| b.iter(|| -x));
34+
}
35+
36+
fn bench_invert<M: ::criterion::measurement::Measurement>(
37+
group: &mut ::criterion::BenchmarkGroup<'_, M>,
38+
) {
39+
let x = core::hint::black_box($fe_a);
40+
group.bench_function("invert", |b| b.iter(|| x.invert()));
41+
}
42+
43+
fn bench_square<'a, M: ::criterion::measurement::Measurement>(
44+
group: &mut ::criterion::BenchmarkGroup<'a, M>,
45+
) {
46+
let x = core::hint::black_box($fe_a);
47+
group.bench_function("square", |b| b.iter(|| x.square()));
48+
}
49+
50+
fn bench_sqrt<'a, M: ::criterion::measurement::Measurement>(
51+
group: &mut ::criterion::BenchmarkGroup<'a, M>,
52+
) {
53+
use ::primefield::ff::Field;
54+
let x = core::hint::black_box($fe_a);
55+
group.bench_function("sqrt", |b| b.iter(|| x.sqrt()));
56+
}
57+
58+
fn $name(c: &mut Criterion) {
59+
let mut group = c.benchmark_group($desc);
60+
bench_add(&mut group);
61+
bench_sub(&mut group);
62+
bench_mul(&mut group);
63+
bench_neg(&mut group);
64+
bench_invert(&mut group);
65+
bench_square(&mut group);
66+
bench_sqrt(&mut group);
67+
group.finish();
68+
}
69+
};
70+
}
71+
172
/// Implement all tests for a type which impls the `PrimeField` trait.
273
#[macro_export]
374
macro_rules! test_primefield {

0 commit comments

Comments
 (0)