From 2ed2157ce347bec8468d05fe9c73417ced1340f8 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 23 Sep 2025 23:00:02 +0200 Subject: [PATCH] numfmt: add benchmark --- Cargo.lock | 2 + src/uu/numfmt/Cargo.toml | 9 ++ src/uu/numfmt/benches/numfmt_bench.rs | 120 ++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 src/uu/numfmt/benches/numfmt_bench.rs diff --git a/Cargo.lock b/Cargo.lock index e5f2b501c..d2cf4d7af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3731,7 +3731,9 @@ name = "uu_numfmt" version = "0.2.2" dependencies = [ "clap", + "codspeed-divan-compat", "fluent", + "tempfile", "thiserror 2.0.16", "uucore", ] diff --git a/src/uu/numfmt/Cargo.toml b/src/uu/numfmt/Cargo.toml index 5cfd2dc46..177f2e3b8 100644 --- a/src/uu/numfmt/Cargo.toml +++ b/src/uu/numfmt/Cargo.toml @@ -23,6 +23,15 @@ uucore = { workspace = true, features = ["parser", "ranges"] } thiserror = { workspace = true } fluent = { workspace = true } +[dev-dependencies] +divan = { workspace = true } +tempfile = { workspace = true } +uucore = { workspace = true, features = ["benchmark"] } + [[bin]] name = "numfmt" path = "src/main.rs" + +[[bench]] +name = "numfmt_bench" +harness = false diff --git a/src/uu/numfmt/benches/numfmt_bench.rs b/src/uu/numfmt/benches/numfmt_bench.rs new file mode 100644 index 000000000..ee09b7d0f --- /dev/null +++ b/src/uu/numfmt/benches/numfmt_bench.rs @@ -0,0 +1,120 @@ +// 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 tempfile::TempDir; +use uu_numfmt::uumain; +use uucore::benchmark::{create_test_file, run_util_function}; + +/// Generate numeric data for benchmarking +fn generate_numbers(count: usize) -> String { + (1..=count) + .map(|n| n.to_string()) + .collect::>() + .join("\n") +} + +/// Setup benchmark environment with test data +fn setup_benchmark(data: String) -> (TempDir, String) { + let temp_dir = tempfile::tempdir().unwrap(); + let file_path = create_test_file(data.as_bytes(), temp_dir.path()); + let file_path_str = file_path.to_str().unwrap().to_string(); + (temp_dir, file_path_str) +} + +/// Benchmark SI formatting with different number counts +#[divan::bench(args = [1_000_000])] +fn numfmt_to_si(bencher: Bencher, count: usize) { + let (_temp_dir, file_path_str) = setup_benchmark(generate_numbers(count)); + + bencher.bench(|| { + black_box(run_util_function(uumain, &["--to=si", &file_path_str])); + }); +} + +/// Benchmark SI formatting with precision format +#[divan::bench(args = [1_000_000])] +fn numfmt_to_si_precision(bencher: Bencher, count: usize) { + let (_temp_dir, file_path_str) = setup_benchmark(generate_numbers(count)); + + bencher.bench(|| { + black_box(run_util_function( + uumain, + &["--to=si", "--format=%.6f", &file_path_str], + )); + }); +} + +/// Benchmark IEC (binary) formatting +#[divan::bench(args = [1_000_000])] +fn numfmt_to_iec(bencher: Bencher, count: usize) { + let (_temp_dir, file_path_str) = setup_benchmark(generate_numbers(count)); + + bencher.bench(|| { + black_box(run_util_function(uumain, &["--to=iec", &file_path_str])); + }); +} + +/// Benchmark parsing from SI format back to raw numbers +#[divan::bench(args = [1_000_000])] +fn numfmt_from_si(bencher: Bencher, count: usize) { + // Generate SI formatted data (e.g., "1.0K", "2.0K", etc.) + let data = (1..=count) + .map(|n| format!("{:.1}K", n as f64 / 1000.0)) + .collect::>() + .join("\n"); + let (_temp_dir, file_path_str) = setup_benchmark(data); + + bencher.bench(|| { + black_box(run_util_function(uumain, &["--from=si", &file_path_str])); + }); +} + +/// Benchmark large numbers with SI formatting +#[divan::bench(args = [1_000_000])] +fn numfmt_large_numbers_si(bencher: Bencher, count: usize) { + // Generate larger numbers (millions to billions range) + let data = (1..=count) + .map(|n| (n * 1_000_000).to_string()) + .collect::>() + .join("\n"); + let (_temp_dir, file_path_str) = setup_benchmark(data); + + bencher.bench(|| { + black_box(run_util_function(uumain, &["--to=si", &file_path_str])); + }); +} + +/// Benchmark different padding widths +#[divan::bench(args = [(1_000_000, 5), (1_000_000, 50)])] +fn numfmt_padding(bencher: Bencher, (count, padding): (usize, usize)) { + let (_temp_dir, file_path_str) = setup_benchmark(generate_numbers(count)); + let padding_arg = format!("--padding={padding}"); + + bencher.bench(|| { + black_box(run_util_function( + uumain, + &["--to=si", &padding_arg, &file_path_str], + )); + }); +} + +/// Benchmark round modes with SI formatting +#[divan::bench(args = [("up", 100_000), ("down", 1_000_000), ("towards-zero", 1_000_000)])] +fn numfmt_round_modes(bencher: Bencher, (round_mode, count): (&str, usize)) { + let (_temp_dir, file_path_str) = setup_benchmark(generate_numbers(count)); + let round_arg = format!("--round={round_mode}"); + + bencher.bench(|| { + black_box(run_util_function( + uumain, + &["--to=si", &round_arg, &file_path_str], + )); + }); +} + +fn main() { + divan::main(); +}