From 365ba7887c48b119fbdb6254af6330e45dbea9d8 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 02:50:20 -0500 Subject: [PATCH 01/11] factor: use num_prime's u64 and u128 factorization methods to speed up the performance of calculating prime numbers for u64 and u128 --- src/uu/factor/src/factor.rs | 97 +++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 14 deletions(-) diff --git a/src/uu/factor/src/factor.rs b/src/uu/factor/src/factor.rs index f3fe92786d3..08233d9299f 100644 --- a/src/uu/factor/src/factor.rs +++ b/src/uu/factor/src/factor.rs @@ -36,26 +36,95 @@ fn print_factors_str( return Ok(()); }; - let (factorization, remaining) = if x > BigUint::from_u32(1).unwrap() { - num_prime::nt_funcs::factors(x.clone(), None) + if x > BigUint::from_u32(1).unwrap() { + // use num_prime's factorize64 algorithm for u64 integers + if x <= BigUint::from_u64(u64::MAX).unwrap() { + let prime_factors = num_prime::nt_funcs::factorize64(x.clone().to_u64_digits()[0]); + write_result_u64(w, &x, prime_factors, print_exponents) + .map_err_context(|| translate!("factor-error-write-error"))?; + } + // use num_prime's factorize128 algorithm for u128 integers + else if x <= BigUint::from_u128(u128::MAX).unwrap() { + let rx = num_str.trim().parse::(); + let Ok(x) = rx else { + // return Ok(). it's non-fatal and we should try the next number. + show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err()); + set_exit_code(1); + return Ok(()); + }; + let prime_factors = num_prime::nt_funcs::factorize128(x); + write_result_u128(w, &x, prime_factors, print_exponents) + .map_err_context(|| translate!("factor-error-write-error"))?; + } + // use num_prime's fallible factorization for anything greater than u128::MAX + else { + let (prime_factors, remaining) = num_prime::nt_funcs::factors(x.clone(), None); + if let Some(_remaining) = remaining { + return Err(USimpleError::new( + 1, + translate!("factor-error-factorization-incomplete"), + )); + } + write_result_biguint(w, &x, prime_factors, print_exponents) + .map_err_context(|| translate!("factor-error-write-error"))?; + } } else { - (BTreeMap::new(), None) - }; - - if let Some(_remaining) = remaining { - return Err(USimpleError::new( - 1, - translate!("factor-error-factorization-incomplete"), - )); + let empty_primes: BTreeMap = BTreeMap::new(); + write_result_biguint(w, &x, empty_primes, print_exponents) + .map_err_context(|| translate!("factor-error-write-error"))?; } - write_result(w, &x, factorization, print_exponents) - .map_err_context(|| translate!("factor-error-write-error"))?; - Ok(()) } -fn write_result( +/// Writing out the prime factors for u64 integers +fn write_result_u64( + w: &mut io::BufWriter, + x: &BigUint, + factorization: BTreeMap, + print_exponents: bool, +) -> io::Result<()> { + write!(w, "{x}:")?; + for (factor, n) in factorization { + if print_exponents { + if n > 1 { + write!(w, " {factor}^{n}")?; + } else { + write!(w, " {factor}")?; + } + } else { + w.write_all(format!(" {factor}").repeat(n).as_bytes())?; + } + } + writeln!(w)?; + w.flush() +} + +/// Writing out the prime factors for u128 integers +fn write_result_u128( + w: &mut io::BufWriter, + x: &u128, + factorization: BTreeMap, + print_exponents: bool, +) -> io::Result<()> { + write!(w, "{x}:")?; + for (factor, n) in factorization { + if print_exponents { + if n > 1 { + write!(w, " {factor}^{n}")?; + } else { + write!(w, " {factor}")?; + } + } else { + w.write_all(format!(" {factor}").repeat(n).as_bytes())?; + } + } + writeln!(w)?; + w.flush() +} + +/// Writing out the prime factors for BigUint integers +fn write_result_biguint( w: &mut io::BufWriter, x: &BigUint, factorization: BTreeMap, From d10f756a6a1a002247c80bb6bbd49268ab46e51f Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 10:27:30 -0500 Subject: [PATCH 02/11] fix cspell issue (renamed function) and changed parsing of u128 digit to add u64 digits from big_uint --- src/uu/factor/src/factor.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/uu/factor/src/factor.rs b/src/uu/factor/src/factor.rs index 08233d9299f..8bf2bafccc0 100644 --- a/src/uu/factor/src/factor.rs +++ b/src/uu/factor/src/factor.rs @@ -45,13 +45,10 @@ fn print_factors_str( } // use num_prime's factorize128 algorithm for u128 integers else if x <= BigUint::from_u128(u128::MAX).unwrap() { - let rx = num_str.trim().parse::(); - let Ok(x) = rx else { - // return Ok(). it's non-fatal and we should try the next number. - show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err()); - set_exit_code(1); - return Ok(()); - }; + // if it's a u128 integer, BigUint will have two u64 digits + // in its Vec, which index 0 is treated as u64::MAX + let big_uint_u64s = x.clone().to_u64_digits(); + let x = u64::MAX as u128 + big_uint_u64s[1] as u128; let prime_factors = num_prime::nt_funcs::factorize128(x); write_result_u128(w, &x, prime_factors, print_exponents) .map_err_context(|| translate!("factor-error-write-error"))?; @@ -65,12 +62,12 @@ fn print_factors_str( translate!("factor-error-factorization-incomplete"), )); } - write_result_biguint(w, &x, prime_factors, print_exponents) + write_result_big_uint(w, &x, prime_factors, print_exponents) .map_err_context(|| translate!("factor-error-write-error"))?; } } else { let empty_primes: BTreeMap = BTreeMap::new(); - write_result_biguint(w, &x, empty_primes, print_exponents) + write_result_big_uint(w, &x, empty_primes, print_exponents) .map_err_context(|| translate!("factor-error-write-error"))?; } @@ -124,7 +121,7 @@ fn write_result_u128( } /// Writing out the prime factors for BigUint integers -fn write_result_biguint( +fn write_result_big_uint( w: &mut io::BufWriter, x: &BigUint, factorization: BTreeMap, From 28fafb96746791206624cbce4898424042cc3937 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 17:31:05 -0500 Subject: [PATCH 03/11] rollback converting from big_uint to u128 --- src/uu/factor/src/factor.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/uu/factor/src/factor.rs b/src/uu/factor/src/factor.rs index 8bf2bafccc0..15af962d659 100644 --- a/src/uu/factor/src/factor.rs +++ b/src/uu/factor/src/factor.rs @@ -45,10 +45,13 @@ fn print_factors_str( } // use num_prime's factorize128 algorithm for u128 integers else if x <= BigUint::from_u128(u128::MAX).unwrap() { - // if it's a u128 integer, BigUint will have two u64 digits - // in its Vec, which index 0 is treated as u64::MAX - let big_uint_u64s = x.clone().to_u64_digits(); - let x = u64::MAX as u128 + big_uint_u64s[1] as u128; + let rx = num_str.trim().parse::(); + let Ok(x) = rx else { + // return Ok(). it's non-fatal and we should try the next number. + show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err()); + set_exit_code(1); + return Ok(()); + }; let prime_factors = num_prime::nt_funcs::factorize128(x); write_result_u128(w, &x, prime_factors, print_exponents) .map_err_context(|| translate!("factor-error-write-error"))?; From d7f5b124457e266221c914ddd2dabc98bfc3c53a Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 17:42:16 -0500 Subject: [PATCH 04/11] factor: base benchmarking for single/multiple u64, u128, and >u128 --- Cargo.lock | 1 + src/uu/factor/Cargo.toml | 8 +++ src/uu/factor/benches/factor_bench.rs | 84 +++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 src/uu/factor/benches/factor_bench.rs diff --git a/Cargo.lock b/Cargo.lock index 311c8eafde9..f1749a8af8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3450,6 +3450,7 @@ name = "uu_factor" version = "0.3.0" dependencies = [ "clap", + "codspeed-divan-compat", "fluent", "num-bigint", "num-prime", diff --git a/src/uu/factor/Cargo.toml b/src/uu/factor/Cargo.toml index 16b56a6ec43..15d09f7a01b 100644 --- a/src/uu/factor/Cargo.toml +++ b/src/uu/factor/Cargo.toml @@ -29,5 +29,13 @@ fluent = { workspace = true } name = "factor" path = "src/main.rs" +[dev-dependencies] +divan = { workspace = true } +uucore = { workspace = true, features = ["benchmark"] } + [lib] path = "src/factor.rs" + +[[bench]] +name = "factor_bench" +harness = false diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs new file mode 100644 index 00000000000..383f5a0f9b7 --- /dev/null +++ b/src/uu/factor/benches/factor_bench.rs @@ -0,0 +1,84 @@ +// This file is part of the uutils coreutils package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +use divan::{Bencher, black_box}; +use uu_factor::uumain; +use uucore::benchmark::run_util_function; + +/// Benchmark one u64 digit +#[divan::bench] +fn factor_single_u64(bencher: Bencher) { + bencher + .with_inputs(|| 1000000_u64) + .bench_values(|single_u64| { + black_box(run_util_function(uumain, &[&single_u64.to_string()])); + }); +} + +/// Benchmark multiple u64 digits +#[divan::bench] +fn factor_multiple_u64s(bencher: Bencher) { + bencher + .with_inputs(|| (2_u64, 1000000_u64)) + .bench_values(|(start_u64, end_u64)| { + for u64_digit in start_u64..=end_u64 { + black_box(run_util_function(uumain, &[&u64_digit.to_string()])); + } + }); +} + +/// Benchmark one u128 digit +#[divan::bench] +fn factor_single_u128(bencher: Bencher) { + bencher + .with_inputs(|| 18446744073709551616_u128) + .bench_values(|single_u128| { + black_box(run_util_function(uumain, &[&single_u128.to_string()])); + }); +} + +/// Benchmark multiple u128 digits +#[divan::bench] +fn factor_multiple_u128s(bencher: Bencher) { + bencher + .with_inputs(|| { + // this is a range of 1 million different u128 integers + (18446744073709551616_u128, 18446744073710551616_u128) + }) + .bench_values(|(start_u128, end_u128)| { + for u128_digit in start_u128..=end_u128 { + black_box(run_util_function(uumain, &[&u128_digit.to_string()])); + } + }); +} + +/// Benchmark single > u128::MAX digits +#[divan::bench] +fn factor_single_big_uint(bencher: Bencher) { + // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 + bencher + .with_inputs(|| "340_282_366_920_938_463_463_374_607_431_768_211_456") + .bench_values(|single_big_uint| { + black_box(run_util_function(uumain, &[single_big_uint])); + }); +} + +/// Benchmark multiple > u128::MAX digits +#[divan::bench] +fn factor_multiple_big_uint(bencher: Bencher) { + // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 + bencher + .with_inputs(|| (768_211_456_u64, 769_211_456_u64)) + .bench_values(|(start_big_uint, end_big_uint)| { + for digit in start_big_uint..=end_big_uint { + let big_uint_str = format!("340282366920938463463374607431768211456{digit}"); + black_box(run_util_function(uumain, &[&big_uint_str])); + } + }); +} + +fn main() { + divan::main(); +} From 5ada98b8597a462293aafe1eee5612f95b7054cd Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 21:02:46 -0500 Subject: [PATCH 05/11] reset factor.rs to original branch code and added uu_factor to benchmarks.yml --- .github/workflows/benchmarks.yml | 1 + src/uu/factor/src/factor.rs | 97 +++++--------------------------- 2 files changed, 15 insertions(+), 83 deletions(-) diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 7485555e0cb..e1c042e23b4 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -43,6 +43,7 @@ jobs: - { package: uu_unexpand } - { package: uu_uniq } - { package: uu_wc } + - { package: uu_factor } steps: - uses: actions/checkout@v5 with: diff --git a/src/uu/factor/src/factor.rs b/src/uu/factor/src/factor.rs index 15af962d659..f3fe92786d3 100644 --- a/src/uu/factor/src/factor.rs +++ b/src/uu/factor/src/factor.rs @@ -36,95 +36,26 @@ fn print_factors_str( return Ok(()); }; - if x > BigUint::from_u32(1).unwrap() { - // use num_prime's factorize64 algorithm for u64 integers - if x <= BigUint::from_u64(u64::MAX).unwrap() { - let prime_factors = num_prime::nt_funcs::factorize64(x.clone().to_u64_digits()[0]); - write_result_u64(w, &x, prime_factors, print_exponents) - .map_err_context(|| translate!("factor-error-write-error"))?; - } - // use num_prime's factorize128 algorithm for u128 integers - else if x <= BigUint::from_u128(u128::MAX).unwrap() { - let rx = num_str.trim().parse::(); - let Ok(x) = rx else { - // return Ok(). it's non-fatal and we should try the next number. - show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err()); - set_exit_code(1); - return Ok(()); - }; - let prime_factors = num_prime::nt_funcs::factorize128(x); - write_result_u128(w, &x, prime_factors, print_exponents) - .map_err_context(|| translate!("factor-error-write-error"))?; - } - // use num_prime's fallible factorization for anything greater than u128::MAX - else { - let (prime_factors, remaining) = num_prime::nt_funcs::factors(x.clone(), None); - if let Some(_remaining) = remaining { - return Err(USimpleError::new( - 1, - translate!("factor-error-factorization-incomplete"), - )); - } - write_result_big_uint(w, &x, prime_factors, print_exponents) - .map_err_context(|| translate!("factor-error-write-error"))?; - } + let (factorization, remaining) = if x > BigUint::from_u32(1).unwrap() { + num_prime::nt_funcs::factors(x.clone(), None) } else { - let empty_primes: BTreeMap = BTreeMap::new(); - write_result_big_uint(w, &x, empty_primes, print_exponents) - .map_err_context(|| translate!("factor-error-write-error"))?; - } - - Ok(()) -} + (BTreeMap::new(), None) + }; -/// Writing out the prime factors for u64 integers -fn write_result_u64( - w: &mut io::BufWriter, - x: &BigUint, - factorization: BTreeMap, - print_exponents: bool, -) -> io::Result<()> { - write!(w, "{x}:")?; - for (factor, n) in factorization { - if print_exponents { - if n > 1 { - write!(w, " {factor}^{n}")?; - } else { - write!(w, " {factor}")?; - } - } else { - w.write_all(format!(" {factor}").repeat(n).as_bytes())?; - } + if let Some(_remaining) = remaining { + return Err(USimpleError::new( + 1, + translate!("factor-error-factorization-incomplete"), + )); } - writeln!(w)?; - w.flush() -} -/// Writing out the prime factors for u128 integers -fn write_result_u128( - w: &mut io::BufWriter, - x: &u128, - factorization: BTreeMap, - print_exponents: bool, -) -> io::Result<()> { - write!(w, "{x}:")?; - for (factor, n) in factorization { - if print_exponents { - if n > 1 { - write!(w, " {factor}^{n}")?; - } else { - write!(w, " {factor}")?; - } - } else { - w.write_all(format!(" {factor}").repeat(n).as_bytes())?; - } - } - writeln!(w)?; - w.flush() + write_result(w, &x, factorization, print_exponents) + .map_err_context(|| translate!("factor-error-write-error"))?; + + Ok(()) } -/// Writing out the prime factors for BigUint integers -fn write_result_big_uint( +fn write_result( w: &mut io::BufWriter, x: &BigUint, factorization: BTreeMap, From e40803962cfcecade187af17f4d9096cf4a1d6ea Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 22:41:23 -0500 Subject: [PATCH 06/11] changed benchmarking to use a smaller range of u64/u128/biguint integers --- src/uu/factor/benches/factor_bench.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs index 383f5a0f9b7..85adf701f6f 100644 --- a/src/uu/factor/benches/factor_bench.rs +++ b/src/uu/factor/benches/factor_bench.rs @@ -21,7 +21,8 @@ fn factor_single_u64(bencher: Bencher) { #[divan::bench] fn factor_multiple_u64s(bencher: Bencher) { bencher - .with_inputs(|| (2_u64, 1000000_u64)) + // this is a range of 50000 million different u128 integers + .with_inputs(|| (2_u64, 50001_u64)) .bench_values(|(start_u64, end_u64)| { for u64_digit in start_u64..=end_u64 { black_box(run_util_function(uumain, &[&u64_digit.to_string()])); @@ -44,8 +45,8 @@ fn factor_single_u128(bencher: Bencher) { fn factor_multiple_u128s(bencher: Bencher) { bencher .with_inputs(|| { - // this is a range of 1 million different u128 integers - (18446744073709551616_u128, 18446744073710551616_u128) + // this is a range of 50000 million different u128 integers + (18446744073709551616_u128, 18446744073709601616_u128) }) .bench_values(|(start_u128, end_u128)| { for u128_digit in start_u128..=end_u128 { @@ -70,7 +71,7 @@ fn factor_single_big_uint(bencher: Bencher) { fn factor_multiple_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher - .with_inputs(|| (768_211_456_u64, 769_211_456_u64)) + .with_inputs(|| (768_211_456_u64, 768_261_456_u64)) .bench_values(|(start_big_uint, end_big_uint)| { for digit in start_big_uint..=end_big_uint { let big_uint_str = format!("340282366920938463463374607431768211456{digit}"); From 51553a4e151d05bc15e0245ee78d3d12aa2e9014 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Fri, 7 Nov 2025 23:21:59 -0500 Subject: [PATCH 07/11] reduced range for big_uint to 25 numbers only --- src/uu/factor/benches/factor_bench.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs index 85adf701f6f..0f23411d472 100644 --- a/src/uu/factor/benches/factor_bench.rs +++ b/src/uu/factor/benches/factor_bench.rs @@ -71,7 +71,7 @@ fn factor_single_big_uint(bencher: Bencher) { fn factor_multiple_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher - .with_inputs(|| (768_211_456_u64, 768_261_456_u64)) + .with_inputs(|| (768_211_456_u64, 768_211_481_u64)) .bench_values(|(start_big_uint, end_big_uint)| { for digit in start_big_uint..=end_big_uint { let big_uint_str = format!("340282366920938463463374607431768211456{digit}"); From 5fb1a8f70f245197b40610b73256a648e3a9a663 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Sat, 8 Nov 2025 00:14:24 -0500 Subject: [PATCH 08/11] reduced factor multiple_big_uint to a range of 3 --- src/uu/factor/benches/factor_bench.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs index 0f23411d472..f4f4dd16778 100644 --- a/src/uu/factor/benches/factor_bench.rs +++ b/src/uu/factor/benches/factor_bench.rs @@ -71,7 +71,7 @@ fn factor_single_big_uint(bencher: Bencher) { fn factor_multiple_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher - .with_inputs(|| (768_211_456_u64, 768_211_481_u64)) + .with_inputs(|| (768_211_456_u64, 768_211_459_u64)) .bench_values(|(start_big_uint, end_big_uint)| { for digit in start_big_uint..=end_big_uint { let big_uint_str = format!("340282366920938463463374607431768211456{digit}"); From b492abd5521ac4235fdd0b10866b73359c0c43d4 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Sat, 8 Nov 2025 02:08:37 -0500 Subject: [PATCH 09/11] lowered divan bench samples and refactored benchmark code to use args from divan macro --- src/uu/factor/benches/factor_bench.rs | 40 ++++++++++++--------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs index f4f4dd16778..5cee8dd1211 100644 --- a/src/uu/factor/benches/factor_bench.rs +++ b/src/uu/factor/benches/factor_bench.rs @@ -8,21 +8,19 @@ use uu_factor::uumain; use uucore::benchmark::run_util_function; /// Benchmark one u64 digit -#[divan::bench] -fn factor_single_u64(bencher: Bencher) { - bencher - .with_inputs(|| 1000000_u64) - .bench_values(|single_u64| { - black_box(run_util_function(uumain, &[&single_u64.to_string()])); - }); +#[divan::bench(args = [1000000])] +fn factor_single_u64(bencher: Bencher, num: u64) { + bencher.with_inputs(|| num).bench_values(|single_u64| { + black_box(run_util_function(uumain, &[&single_u64.to_string()])); + }); } /// Benchmark multiple u64 digits -#[divan::bench] -fn factor_multiple_u64s(bencher: Bencher) { +#[divan::bench(args = [(2, 50001)])] +fn factor_multiple_u64s(bencher: Bencher, (start_num, end_num): (u64, u64)) { bencher // this is a range of 50000 million different u128 integers - .with_inputs(|| (2_u64, 50001_u64)) + .with_inputs(|| (start_num, end_num)) .bench_values(|(start_u64, end_u64)| { for u64_digit in start_u64..=end_u64 { black_box(run_util_function(uumain, &[&u64_digit.to_string()])); @@ -31,22 +29,20 @@ fn factor_multiple_u64s(bencher: Bencher) { } /// Benchmark one u128 digit -#[divan::bench] -fn factor_single_u128(bencher: Bencher) { - bencher - .with_inputs(|| 18446744073709551616_u128) - .bench_values(|single_u128| { - black_box(run_util_function(uumain, &[&single_u128.to_string()])); - }); +#[divan::bench(args = [18446744073709551616])] +fn factor_single_u128(bencher: Bencher, num: u128) { + bencher.with_inputs(|| num).bench_values(|single_u128| { + black_box(run_util_function(uumain, &[&single_u128.to_string()])); + }); } /// Benchmark multiple u128 digits -#[divan::bench] -fn factor_multiple_u128s(bencher: Bencher) { +#[divan::bench(args = [(18446744073709551616, 18446744073709601616)])] +fn factor_multiple_u128s(bencher: Bencher, (start_num, end_num): (u128, u128)) { bencher .with_inputs(|| { // this is a range of 50000 million different u128 integers - (18446744073709551616_u128, 18446744073709601616_u128) + (start_num, end_num) }) .bench_values(|(start_u128, end_u128)| { for u128_digit in start_u128..=end_u128 { @@ -56,7 +52,7 @@ fn factor_multiple_u128s(bencher: Bencher) { } /// Benchmark single > u128::MAX digits -#[divan::bench] +#[divan::bench(sample_size = 25)] fn factor_single_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher @@ -67,7 +63,7 @@ fn factor_single_big_uint(bencher: Bencher) { } /// Benchmark multiple > u128::MAX digits -#[divan::bench] +#[divan::bench(sample_size = 25)] fn factor_multiple_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher From 9e788c72e527f29c49e3b965e69a3562272e2f4c Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Sat, 8 Nov 2025 02:20:23 -0500 Subject: [PATCH 10/11] factor/bench: big_uint only benchmarks numbers that num_prime can factorize properly (factorize error take a while to propagate) --- src/uu/factor/benches/factor_bench.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs index 5cee8dd1211..78ebda3c9d3 100644 --- a/src/uu/factor/benches/factor_bench.rs +++ b/src/uu/factor/benches/factor_bench.rs @@ -52,7 +52,7 @@ fn factor_multiple_u128s(bencher: Bencher, (start_num, end_num): (u128, u128)) { } /// Benchmark single > u128::MAX digits -#[divan::bench(sample_size = 25)] +#[divan::bench] fn factor_single_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher @@ -63,11 +63,11 @@ fn factor_single_big_uint(bencher: Bencher) { } /// Benchmark multiple > u128::MAX digits -#[divan::bench(sample_size = 25)] +#[divan::bench] fn factor_multiple_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher - .with_inputs(|| (768_211_456_u64, 768_211_459_u64)) + .with_inputs(|| (768_211_459_u64, 768_211_461_u64)) .bench_values(|(start_big_uint, end_big_uint)| { for digit in start_big_uint..=end_big_uint { let big_uint_str = format!("340282366920938463463374607431768211456{digit}"); From d977e299a03d63331f823e47cf7942a115d9a088 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Sat, 8 Nov 2025 13:07:27 -0500 Subject: [PATCH 11/11] factor/bench: reduced range on u64 and u128 benchmarking and remove single u64/u128/big_uint benchmark tests --- src/uu/factor/benches/factor_bench.rs | 45 ++++++--------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/src/uu/factor/benches/factor_bench.rs b/src/uu/factor/benches/factor_bench.rs index 78ebda3c9d3..121865ac018 100644 --- a/src/uu/factor/benches/factor_bench.rs +++ b/src/uu/factor/benches/factor_bench.rs @@ -7,20 +7,12 @@ use divan::{Bencher, black_box}; use uu_factor::uumain; use uucore::benchmark::run_util_function; -/// Benchmark one u64 digit -#[divan::bench(args = [1000000])] -fn factor_single_u64(bencher: Bencher, num: u64) { - bencher.with_inputs(|| num).bench_values(|single_u64| { - black_box(run_util_function(uumain, &[&single_u64.to_string()])); - }); -} - /// Benchmark multiple u64 digits -#[divan::bench(args = [(2, 50001)])] -fn factor_multiple_u64s(bencher: Bencher, (start_num, end_num): (u64, u64)) { +#[divan::bench(args = [(2)])] +fn factor_multiple_u64s(bencher: Bencher, start_num: u64) { bencher - // this is a range of 50000 million different u128 integers - .with_inputs(|| (start_num, end_num)) + // this is a range of 5000 different u128 integers + .with_inputs(|| (start_num, start_num + 2500)) .bench_values(|(start_u64, end_u64)| { for u64_digit in start_u64..=end_u64 { black_box(run_util_function(uumain, &[&u64_digit.to_string()])); @@ -28,21 +20,13 @@ fn factor_multiple_u64s(bencher: Bencher, (start_num, end_num): (u64, u64)) { }); } -/// Benchmark one u128 digit -#[divan::bench(args = [18446744073709551616])] -fn factor_single_u128(bencher: Bencher, num: u128) { - bencher.with_inputs(|| num).bench_values(|single_u128| { - black_box(run_util_function(uumain, &[&single_u128.to_string()])); - }); -} - /// Benchmark multiple u128 digits -#[divan::bench(args = [(18446744073709551616, 18446744073709601616)])] -fn factor_multiple_u128s(bencher: Bencher, (start_num, end_num): (u128, u128)) { +#[divan::bench(args = [(18446744073709551616)])] +fn factor_multiple_u128s(bencher: Bencher, start_num: u128) { bencher .with_inputs(|| { - // this is a range of 50000 million different u128 integers - (start_num, end_num) + // this is a range of 1000 different u128 integers + (start_num, start_num + 1000) }) .bench_values(|(start_u128, end_u128)| { for u128_digit in start_u128..=end_u128 { @@ -51,22 +35,13 @@ fn factor_multiple_u128s(bencher: Bencher, (start_num, end_num): (u128, u128)) { }); } -/// Benchmark single > u128::MAX digits -#[divan::bench] -fn factor_single_big_uint(bencher: Bencher) { - // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 - bencher - .with_inputs(|| "340_282_366_920_938_463_463_374_607_431_768_211_456") - .bench_values(|single_big_uint| { - black_box(run_util_function(uumain, &[single_big_uint])); - }); -} - /// Benchmark multiple > u128::MAX digits #[divan::bench] fn factor_multiple_big_uint(bencher: Bencher) { // max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455 bencher + // this is a range of 3 different BigUints. The range is small due to + // some BigUints being unable to be factorized into prime numbers properly .with_inputs(|| (768_211_459_u64, 768_211_461_u64)) .bench_values(|(start_big_uint, end_big_uint)| { for digit in start_big_uint..=end_big_uint {