265 lines
8.2 KiB
Rust
265 lines
8.2 KiB
Rust
use criterion::{
|
|
criterion_group, criterion_main, measurement::Measurement, BatchSize, BenchmarkGroup, Criterion,
|
|
};
|
|
use crypto_bigint::{
|
|
modular::runtime_mod::{DynResidue, DynResidueParams},
|
|
Limb, MultiExponentiate, NonZero, Random, Reciprocal, U128, U2048, U256,
|
|
};
|
|
use rand_core::OsRng;
|
|
|
|
fn bench_division<M: Measurement>(group: &mut BenchmarkGroup<'_, M>) {
|
|
group.bench_function("div/rem, U256/U128, full size", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = U256::random(&mut OsRng);
|
|
let y_half = U128::random(&mut OsRng);
|
|
let y: U256 = (y_half, U128::ZERO).into();
|
|
(x, NonZero::new(y).unwrap())
|
|
},
|
|
|(x, y)| x.div_rem(&y),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("rem, U256/U128, full size", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = U256::random(&mut OsRng);
|
|
let y_half = U128::random(&mut OsRng);
|
|
let y: U256 = (y_half, U128::ZERO).into();
|
|
(x, NonZero::new(y).unwrap())
|
|
},
|
|
|(x, y)| x.rem(&y),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("div/rem, U256/Limb, full size", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = U256::random(&mut OsRng);
|
|
let y_small = Limb::random(&mut OsRng);
|
|
let y = U256::from_word(y_small.0);
|
|
(x, NonZero::new(y).unwrap())
|
|
},
|
|
|(x, y)| x.div_rem(&y),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("div/rem, U256/Limb, single limb", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = U256::random(&mut OsRng);
|
|
let y = Limb::random(&mut OsRng);
|
|
(x, NonZero::new(y).unwrap())
|
|
},
|
|
|(x, y)| x.div_rem_limb(y),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("div/rem, U256/Limb, single limb with reciprocal", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = U256::random(&mut OsRng);
|
|
let y = Limb::random(&mut OsRng);
|
|
let r = Reciprocal::new(y);
|
|
(x, r)
|
|
},
|
|
|(x, r)| x.div_rem_limb_with_reciprocal(&r),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
}
|
|
|
|
fn bench_montgomery_ops<M: Measurement>(group: &mut BenchmarkGroup<'_, M>) {
|
|
let params = DynResidueParams::new(&(U256::random(&mut OsRng) | U256::ONE));
|
|
group.bench_function("multiplication, U256*U256", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = DynResidue::new(&U256::random(&mut OsRng), params);
|
|
let y = DynResidue::new(&U256::random(&mut OsRng), params);
|
|
(x, y)
|
|
},
|
|
|(x, y)| x * y,
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
let m = U256::random(&mut OsRng) | U256::ONE;
|
|
let params = DynResidueParams::new(&m);
|
|
group.bench_function("modpow, U256^U256", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let x = U256::random(&mut OsRng);
|
|
let x_m = DynResidue::new(&x, params);
|
|
let p = U256::random(&mut OsRng) | (U256::ONE << (U256::BITS - 1));
|
|
(x_m, p)
|
|
},
|
|
|(x, p)| x.pow(&p),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
for i in [1, 2, 3, 4, 10, 100] {
|
|
group.bench_function(
|
|
format!("multi_exponentiate for {i} bases, U256^U256"),
|
|
|b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let bases_and_exponents: Vec<(DynResidue<{ U256::LIMBS }>, U256)> = (1..=i)
|
|
.map(|_| {
|
|
let x = U256::random(&mut OsRng);
|
|
let x_m = DynResidue::new(&x, params);
|
|
let p = U256::random(&mut OsRng) | (U256::ONE << (U256::BITS - 1));
|
|
(x_m, p)
|
|
})
|
|
.collect();
|
|
|
|
bases_and_exponents
|
|
},
|
|
|bases_and_exponents| {
|
|
DynResidue::<{ U256::LIMBS }>::multi_exponentiate(
|
|
bases_and_exponents.as_slice(),
|
|
)
|
|
},
|
|
BatchSize::SmallInput,
|
|
)
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
fn bench_montgomery_conversion<M: Measurement>(group: &mut BenchmarkGroup<'_, M>) {
|
|
group.bench_function("DynResidueParams creation", |b| {
|
|
b.iter_batched(
|
|
|| U256::random(&mut OsRng) | U256::ONE,
|
|
|modulus| DynResidueParams::new(&modulus),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
let params = DynResidueParams::new(&(U256::random(&mut OsRng) | U256::ONE));
|
|
group.bench_function("DynResidue creation", |b| {
|
|
b.iter_batched(
|
|
|| U256::random(&mut OsRng),
|
|
|x| DynResidue::new(&x, params),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
let params = DynResidueParams::new(&(U256::random(&mut OsRng) | U256::ONE));
|
|
group.bench_function("DynResidue retrieve", |b| {
|
|
b.iter_batched(
|
|
|| DynResidue::new(&U256::random(&mut OsRng), params),
|
|
|x| x.retrieve(),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
}
|
|
|
|
fn bench_shifts<M: Measurement>(group: &mut BenchmarkGroup<'_, M>) {
|
|
group.bench_function("shl_vartime, small, U2048", |b| {
|
|
b.iter_batched(|| U2048::ONE, |x| x.shl_vartime(10), BatchSize::SmallInput)
|
|
});
|
|
|
|
group.bench_function("shl_vartime, large, U2048", |b| {
|
|
b.iter_batched(
|
|
|| U2048::ONE,
|
|
|x| x.shl_vartime(1024 + 10),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("shl, U2048", |b| {
|
|
b.iter_batched(|| U2048::ONE, |x| x.shl(1024 + 10), BatchSize::SmallInput)
|
|
});
|
|
|
|
group.bench_function("shr, U2048", |b| {
|
|
b.iter_batched(|| U2048::ONE, |x| x.shr(1024 + 10), BatchSize::SmallInput)
|
|
});
|
|
}
|
|
|
|
fn bench_inv_mod<M: Measurement>(group: &mut BenchmarkGroup<'_, M>) {
|
|
group.bench_function("inv_odd_mod, U256", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let m = U256::random(&mut OsRng) | U256::ONE;
|
|
loop {
|
|
let x = U256::random(&mut OsRng);
|
|
let (_, is_some) = x.inv_odd_mod(&m);
|
|
if is_some.into() {
|
|
break (x, m);
|
|
}
|
|
}
|
|
},
|
|
|(x, m)| x.inv_odd_mod(&m),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("inv_mod, U256, odd modulus", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let m = U256::random(&mut OsRng) | U256::ONE;
|
|
loop {
|
|
let x = U256::random(&mut OsRng);
|
|
let (_, is_some) = x.inv_odd_mod(&m);
|
|
if is_some.into() {
|
|
break (x, m);
|
|
}
|
|
}
|
|
},
|
|
|(x, m)| x.inv_mod(&m),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
|
|
group.bench_function("inv_mod, U256", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
let m = U256::random(&mut OsRng);
|
|
loop {
|
|
let x = U256::random(&mut OsRng);
|
|
let (_, is_some) = x.inv_mod(&m);
|
|
if is_some.into() {
|
|
break (x, m);
|
|
}
|
|
}
|
|
},
|
|
|(x, m)| x.inv_mod(&m),
|
|
BatchSize::SmallInput,
|
|
)
|
|
});
|
|
}
|
|
|
|
fn bench_wrapping_ops(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("wrapping ops");
|
|
bench_division(&mut group);
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_montgomery(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("Montgomery arithmetic");
|
|
bench_montgomery_conversion(&mut group);
|
|
bench_montgomery_ops(&mut group);
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_modular_ops(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("modular ops");
|
|
bench_shifts(&mut group);
|
|
bench_inv_mod(&mut group);
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
bench_wrapping_ops,
|
|
bench_montgomery,
|
|
bench_modular_ops
|
|
);
|
|
|
|
criterion_main!(benches);
|