From c1e530eedade0b8beb78a2086e3aa444792d2ec2 Mon Sep 17 00:00:00 2001 From: Jacob Zhong Date: Sun, 17 Apr 2022 22:22:05 -0400 Subject: [PATCH] Add more benchmarks --- Cargo.toml | 10 ++-- bench/Cargo.toml | 23 +++++++++ bench/benches/bench.rs | 113 +++++++++++++++++++++++++++++++++++++++++ benches/bench.rs | 57 --------------------- 4 files changed, 140 insertions(+), 63 deletions(-) create mode 100644 bench/Cargo.toml create mode 100644 bench/benches/bench.rs delete mode 100644 benches/bench.rs diff --git a/Cargo.toml b/Cargo.toml index cc98a09..56e7f1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,12 +34,10 @@ default = ['big-table', 'big-int'] big-table = [] big-int = ['num-bigint', 'num-modular/num-bigint'] -[dev-dependencies] -criterion = "0.3" - -[[bench]] -name = "bench" -harness = false +[workspace] +members = [ + "bench", +] [package.metadata.docs.rs] all-features = true diff --git a/bench/Cargo.toml b/bench/Cargo.toml new file mode 100644 index 0000000..a19ff24 --- /dev/null +++ b/bench/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "num-prime-bench" +version = "0.0.0" +publish = false +edition = "2018" + +[[bench]] +name = "bench" +harness = false + +[dependencies] +num-bigint = "0.4" +num-prime = { path = ".." } +criterion = "0.3" +rand = "0.8" + +num-primes = { version = "0.3.0", optional = true } +primal-check = "0.3.1" +number-theory = "0.0.6" +is_prime = "2.0.7" + +[features] +default = ["num-primes"] diff --git a/bench/benches/bench.rs b/bench/benches/bench.rs new file mode 100644 index 0000000..e34ca56 --- /dev/null +++ b/bench/benches/bench.rs @@ -0,0 +1,113 @@ +#[macro_use] +extern crate criterion; +use criterion::{Criterion, SamplingMode}; +use num_prime::{nt_funcs, RandPrime}; +#[cfg(feature = "num-primes")] +use num_primes::{Generator, Verification}; +use primal_check::miller_rabin; +use number_theory::NumberTheory; + +pub fn bench_is_prime(c: &mut Criterion) { + const N0: u64 = 1_000_000; + const STEP: usize = 101; + const N1: u64 = 8_000_000_000; // larger than u32 + const N2: u64 = N1 + N0; + + let numbers = || (1..N0) + .step_by(STEP) + .chain((N1..N2).step_by(STEP)); + + let mut group = c.benchmark_group("is_prime (u64)"); + + group.bench_function("num-prime (this crate)", |b| { + b.iter(|| { + numbers() + .filter(|&n| nt_funcs::is_prime64(n)) + .count() + }) + }); + #[cfg(feature = "num-primes")] + group.bench_function("num-primes", |b| { + b.iter(|| { + numbers() + .filter(|&n| Verification::is_prime(&n.into())) + .count() + }) + }); + group.bench_function("primal-check", |b| { + b.iter(|| { + numbers() + .filter(|&n| miller_rabin(n)) + .count() + }) + }); + group.bench_function("number-theory", |b| { + b.iter(|| { + numbers() + .filter(|&n| NumberTheory::is_prime(&n)) + .count() + }) + }); + // TODO(v0.4.1): why is number-theory faster? difference in modular power? + // we can add a markdown of performance after figuring out this + + group.finish(); +} + +pub fn bench_factorization(c: &mut Criterion) { + const N0: u64 = 1_000_000; + const STEP: usize = 501; + const N1: u64 = 8_000_000_000; // larger than u32 + const N2: u64 = N1 + N0; + + let numbers = || (1..N0) + .step_by(STEP) + .chain((N1..N2).step_by(STEP)); + let mut group = c.benchmark_group("factorize (u64)"); + + group.bench_function("num-prime (this crate)", |b| { + b.iter(|| { + numbers() + .filter(|&n| nt_funcs::factorize64(n as u64).len() > 1) + .count() + }) + }); + group.bench_function("number-theory", |b| { + b.iter(|| { + numbers() + .filter(|&n| NumberTheory::factor(&n).len() > 1) + .count() + }) + }); + + group.finish(); +} + +pub fn bench_prime_gen(c: &mut Criterion) { + let mut group = c.benchmark_group("prime generation (256 bits)"); + group.sample_size(10).sampling_mode(SamplingMode::Flat); + + let mut gen = rand::thread_rng(); + group.bench_function("num-prime (this crate)", |b| { + b.iter(|| -> num_bigint::BigUint { gen.gen_prime(256, None) }) + }); + group.bench_function("num-primes", |b| { + b.iter(|| Generator::new_prime(256)) + }); + group.finish(); + + let mut group = c.benchmark_group("safe prime generation (256 bits)"); + group.sample_size(10).sampling_mode(SamplingMode::Flat); + + let mut gen = rand::thread_rng(); + group.bench_function("num-prime (this crate)", |b| { + b.iter(|| -> num_bigint::BigUint { gen.gen_safe_prime(256) }) + }); + group.bench_function("num-primes", |b| { + b.iter(|| Generator::safe_prime(256)) + }); + group.finish(); +} + +criterion_group!(benches, bench_is_prime, bench_factorization, bench_prime_gen); +criterion_main!(benches); diff --git a/benches/bench.rs b/benches/bench.rs deleted file mode 100644 index 44ae168..0000000 --- a/benches/bench.rs +++ /dev/null @@ -1,57 +0,0 @@ -#[macro_use] -extern crate criterion; -use criterion::Criterion; -use num_prime::nt_funcs; - -pub fn bench_is_prime(c: &mut Criterion) { - const N: usize = 1_000_000; - const STEP: usize = 101; - let mut group = c.benchmark_group("is_prime"); - - group.bench_function("64bit", |b| { - b.iter(|| { - (1..N) - .step_by(STEP) - .filter(|&n| nt_funcs::is_prime64(n as u64)) - .count() - }) - }); - group.bench_function("default config", |b| { - b.iter(|| { - (1..N) - .step_by(STEP) - .filter(|&n| nt_funcs::is_prime(&(n as u64), None).probably()) - .count() - }) - }); - - group.finish(); -} - -pub fn bench_factorization(c: &mut Criterion) { - const N: usize = 1_000_000; - const STEP: usize = 501; - let mut group = c.benchmark_group("factors"); - - group.bench_function("64bit", |b| { - b.iter(|| { - (1..N) - .step_by(STEP) - .filter(|&n| nt_funcs::factorize64(n as u64).len() > 1) - .count() - }) - }); - group.bench_function("default config", |b| { - b.iter(|| { - (1..N) - .step_by(STEP) - .filter(|&n| nt_funcs::factors(n as u64, None).is_ok()) - .count() - }) - }); - - group.finish(); -} - -criterion_group!(benches, bench_is_prime, bench_factorization); -criterion_main!(benches);