From 330e0bc0f80b9f7bfe131816d4b48f331c187978 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:04:15 +0000 Subject: [PATCH] benchmarks: prepare args outside benchmark --- src/uu/base64/benches/base64_bench.rs | 63 ++++---- src/uu/cksum/benches/cksum_bench.rs | 83 +++++------ src/uu/cp/benches/cp_bench.rs | 20 +-- src/uu/cut/benches/cut_bench.rs | 47 ++---- src/uu/date/benches/date_bench.rs | 41 +++--- src/uu/df/benches/df_bench.rs | 18 ++- src/uu/du/benches/du_bench.rs | 101 +++++++------ src/uu/expand/benches/expand_bench.rs | 32 ++-- src/uu/fold/benches/fold_bench.rs | 21 ++- src/uu/seq/benches/seq_bench.rs | 35 ++--- src/uu/shuf/benches/shuf_bench.rs | 25 ++-- src/uu/sort/benches/sort_bench.rs | 137 ++++++------------ src/uu/sort/benches/sort_locale_c_bench.rs | 35 ++--- src/uu/sort/benches/sort_locale_de_bench.rs | 13 +- src/uu/sort/benches/sort_locale_utf8_bench.rs | 62 ++++---- src/uu/split/benches/split_bench.rs | 42 +++--- src/uu/tsort/benches/tsort_bench.rs | 37 ++--- src/uu/unexpand/benches/unexpand_bench.rs | 16 +- src/uu/uniq/benches/uniq_bench.rs | 23 ++- src/uu/wc/benches/wc_bench.rs | 65 ++++----- src/uucore/src/lib/features/benchmark.rs | 8 + 21 files changed, 395 insertions(+), 529 deletions(-) diff --git a/src/uu/base64/benches/base64_bench.rs b/src/uu/base64/benches/base64_bench.rs index b157af0c85b..0a41b36b82a 100644 --- a/src/uu/base64/benches/base64_bench.rs +++ b/src/uu/base64/benches/base64_bench.rs @@ -4,67 +4,58 @@ // file that was distributed with this source code. use divan::{Bencher, black_box}; -use std::ffi::OsString; use uu_base64::uumain; -use uucore::benchmark::{create_test_file, run_util_function, text_data}; +use uucore::benchmark::{create_test_file, get_bench_args, text_data}; -fn create_tmp_file(size_mb: usize) -> String { +fn create_tmp_file(size_mb: usize) -> std::path::PathBuf { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_size(size_mb, 80); - let file_path = create_test_file(&data, temp_dir.path()); - String::from(file_path.to_str().unwrap()) + create_test_file(&data, temp_dir.path()) +} + +fn redirect_in(in_file: &std::path::Path) -> std::ffi::OsString { + std::iter::once(std::ffi::OsString::from(">").as_os_str()) + .chain(std::iter::once(in_file.as_os_str())) + .collect() } /// Benchmark for base64 encoding #[divan::bench()] fn b64_encode_synthetic(bencher: Bencher) { - let file_path_str = &create_tmp_file(5_000); + let file_path = create_tmp_file(5_000); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } // Benchmark for base64 decoding #[divan::bench()] fn b64_decode_synthetic(bencher: Bencher) { let temp_dir = tempfile::tempdir().unwrap(); - let file_path_str = &create_tmp_file(5_000); + let file_path = create_tmp_file(5_000); let in_file = create_test_file(b"", temp_dir.path()); - let in_file_str = in_file.to_str().unwrap(); - uumain( - [ - OsString::from(file_path_str), - OsString::from(format!(">{in_file_str}")), - ] - .iter() - .map(|x| (*x).clone()), - ); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-d", in_file_str])); - }); + uumain([file_path.into(), redirect_in(&in_file)].into_iter()); + + bencher + .with_inputs(|| get_bench_args(&[&"-d", &in_file]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } // Benchmark different file sizes for base64 decoding ignoring garbage characters #[divan::bench()] fn b64_decode_ignore_garbage_synthetic(bencher: Bencher) { - let temp_dir = tempfile::tempdir().unwrap(); - let file_path_str = &create_tmp_file(5_000); + let tempdir = tempfile::tempdir().unwrap(); + let temp_dir = tempdir; + let file_path = create_tmp_file(5_000); let in_file = create_test_file(b"", temp_dir.path()); - let in_file_str = in_file.to_str().unwrap(); - uumain( - [ - OsString::from(file_path_str), - OsString::from(format!(">{in_file_str}")), - ] - .iter() - .map(|x| (*x).clone()), - ); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-d", "-i", in_file_str])); - }); + uumain([file_path.into(), redirect_in(&in_file)].into_iter()); + + bencher + .with_inputs(|| get_bench_args(&[&"-d", &"-i", &in_file]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/cksum/benches/cksum_bench.rs b/src/uu/cksum/benches/cksum_bench.rs index 81f70bbb3d1..f96bff54dc9 100644 --- a/src/uu/cksum/benches/cksum_bench.rs +++ b/src/uu/cksum/benches/cksum_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_cksum::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; // Macro to generate benchmarks for each algorithm macro_rules! bench_algorithm { @@ -15,12 +15,11 @@ macro_rules! bench_algorithm { let data = text_data::generate_by_size(100, 80); let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["--algorithm", $algo_str, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| { + get_bench_args(&[&"--algorithm", &$algo_str, &file_path]).into_iter() + }) + .bench_values(|args| black_box(uumain(args))); } }; ($algo_name:ident, $algo_str:expr, $length:expr) => { @@ -29,18 +28,18 @@ macro_rules! bench_algorithm { let data = text_data::generate_by_size(100, 80); let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &[ - "--algorithm", - $algo_str, - "--length", - $length, - file_path.to_str().unwrap(), - ], - )); - }); + bencher + .with_inputs(|| { + get_bench_args(&[ + &"--algorithm", + &$algo_str, + &"--length", + &$length, + &file_path, + ]) + .into_iter() + }) + .bench_values(|args| black_box(uumain(args))); } }; } @@ -114,9 +113,9 @@ fn cksum_default(bencher: Bencher) { let data = text_data::generate_by_size(100, 80); let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path.to_str().unwrap()])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark cksum with raw output format @@ -125,39 +124,25 @@ fn cksum_raw_output(bencher: Bencher) { let data = text_data::generate_by_size(100, 80); let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["--raw", file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"--raw", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark cksum processing multiple files #[divan::bench] fn cksum_multiple_files(bencher: Bencher) { + let data1 = text_data::generate_by_size(50, 80); + let data2 = text_data::generate_by_size(50, 80); + let data3 = text_data::generate_by_size(50, 80); + + let file1 = setup_test_file(&data1); + let file2 = setup_test_file(&data2); + let file3 = setup_test_file(&data3); + bencher - .with_inputs(|| { - let data1 = text_data::generate_by_size(50, 80); - let data2 = text_data::generate_by_size(50, 80); - let data3 = text_data::generate_by_size(50, 80); - - let file1 = setup_test_file(&data1); - let file2 = setup_test_file(&data2); - let file3 = setup_test_file(&data3); - - (file1, file2, file3) - }) - .bench_values(|(file1, file2, file3)| { - black_box(run_util_function( - uumain, - &[ - file1.to_str().unwrap(), - file2.to_str().unwrap(), - file3.to_str().unwrap(), - ], - )); - }); + .with_inputs(|| get_bench_args(&[&file1, &file2, &file3]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/cp/benches/cp_bench.rs b/src/uu/cp/benches/cp_bench.rs index 84954f0bb54..ffc514fe3e3 100644 --- a/src/uu/cp/benches/cp_bench.rs +++ b/src/uu/cp/benches/cp_bench.rs @@ -8,7 +8,7 @@ use std::fs; use std::path::Path; use tempfile::TempDir; use uu_cp::uumain; -use uucore::benchmark::{binary_data, fs_tree, fs_utils, run_util_function}; +use uucore::benchmark::{binary_data, fs_tree, fs_utils, get_bench_args, run_util_function}; fn bench_cp_directory(bencher: Bencher, args: &[&str], setup_source: F) where @@ -87,20 +87,14 @@ fn cp_large_file(bencher: Bencher, size_mb: usize) { let temp_dir = TempDir::new().unwrap(); let source = temp_dir.path().join("source.bin"); binary_data::create_file(&source, size_mb, b'x'); - (temp_dir, source) + // Use unique destination name to avoid filesystem allocation variance + let dest = temp_dir + .path() + .join(format!("dest_{}.bin", (&raw const temp_dir).addr())); + get_bench_args(&[&source, &dest]).into_iter() }) .counter(divan::counter::BytesCount::new(size_mb * 1024 * 1024)) - .bench_values(|(temp_dir, source)| { - // Use unique destination name to avoid filesystem allocation variance - let dest = temp_dir.path().join(format!( - "dest_{}.bin", - std::ptr::addr_of!(temp_dir) as usize - )); - let source_str = source.to_str().unwrap(); - let dest_str = dest.to_str().unwrap(); - - black_box(run_util_function(uumain, &[source_str, dest_str])); - }); + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/cut/benches/cut_bench.rs b/src/uu/cut/benches/cut_bench.rs index c0288a8546e..f5a85872242 100644 --- a/src/uu/cut/benches/cut_bench.rs +++ b/src/uu/cut/benches/cut_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_cut::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; /// Benchmark cutting specific byte ranges #[divan::bench] @@ -13,12 +13,9 @@ fn cut_bytes(bencher: Bencher) { let data = text_data::generate_by_lines(100_000, 80); let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-b", "1-20", file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-b", &"1-20", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark cutting specific character ranges @@ -27,12 +24,9 @@ fn cut_characters(bencher: Bencher) { let data = text_data::generate_mixed_data(100_000); let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-c", "5-30", file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-c", &"5-30", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark cutting fields with tab delimiter @@ -45,12 +39,9 @@ fn cut_fields_tab(bencher: Bencher) { } let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-f", "2,4", file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-f", &"2,4", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark cutting fields with custom delimiter @@ -63,12 +54,9 @@ fn cut_fields_custom_delim(bencher: Bencher) { } let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-d", ",", "-f", "1,3,5", file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-d", &",", &"-f", &"1,3,5", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark cutting fields with newline delimiter @@ -81,12 +69,9 @@ fn cut_fields_newline_delim(bencher: Bencher) { } let file_path = setup_test_file(&data); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-d", "\n", "-f", "1,3,5", file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-d", &"\n", &"-f", &"1,3,5", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/date/benches/date_bench.rs b/src/uu/date/benches/date_bench.rs index 1c1d05aaea2..a74a3a4c822 100644 --- a/src/uu/date/benches/date_bench.rs +++ b/src/uu/date/benches/date_bench.rs @@ -7,7 +7,7 @@ use divan::{Bencher, black_box}; use std::io::Write; use tempfile::NamedTempFile; use uu_date::uumain; -use uucore::benchmark::run_util_function; +use uucore::benchmark::get_bench_args; /// Helper to create a temporary file containing N lines of date strings. fn setup_date_file(lines: usize, date_format: &str) -> NamedTempFile { @@ -23,11 +23,11 @@ fn setup_date_file(lines: usize, date_format: &str) -> NamedTempFile { fn file_iso_dates(bencher: Bencher) { let count = 1_000; let file = setup_date_file(count, "2023-05-10 12:00:00"); - let path = file.path().to_str().unwrap(); + let path = file.path(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-f", path])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-f", &path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmarks processing a file containing dates with Timezone abbreviations. @@ -36,11 +36,11 @@ fn file_tz_abbreviations(bencher: Bencher) { let count = 1_000; // "EST" triggers the abbreviation lookup and double-parsing logic let file = setup_date_file(count, "2023-05-10 12:00:00 EST"); - let path = file.path().to_str().unwrap(); + let path = file.path(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-f", path])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-f", &path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmarks formatting speed using a custom output format. @@ -48,30 +48,27 @@ fn file_tz_abbreviations(bencher: Bencher) { fn file_custom_format(bencher: Bencher) { let count = 1_000; let file = setup_date_file(count, "2023-05-10 12:00:00"); - let path = file.path().to_str().unwrap(); + let path = file.path(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-f", path, "+%A %d %B %Y"])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-f", &path, &"+%A %d %B %Y"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmarks the overhead of starting the utility for a single date (no file). #[divan::bench] fn single_date_now(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function(uumain, &[])); - }); + bencher + .with_inputs(|| get_bench_args(&[]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmarks parsing a complex relative date string passed as an argument. #[divan::bench] fn complex_relative_date(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["--date=last friday 12:00 + 2 days"], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"--date=last friday 12:00 + 2 days"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/df/benches/df_bench.rs b/src/uu/df/benches/df_bench.rs index f678f7f7b9a..50d3dd180b6 100644 --- a/src/uu/df/benches/df_bench.rs +++ b/src/uu/df/benches/df_bench.rs @@ -9,7 +9,7 @@ use std::fs; use std::path::PathBuf; use tempfile::TempDir; use uu_df::uumain; -use uucore::benchmark::run_util_function; +use uucore::benchmark::get_bench_args; fn create_deep_directory(base_dir: &std::path::Path, depth: usize) -> PathBuf { let mut current = base_dir.to_path_buf(); @@ -30,9 +30,10 @@ fn df_deep_directory(bencher: Bencher) { let original_dir = env::current_dir().unwrap(); let temp_dir = TempDir::new().unwrap(); let _deep_path = create_deep_directory(temp_dir.path(), DEPTH); - bencher.bench(|| { - black_box(run_util_function(uumain, &[] as &[&str])); - }); + + bencher + .with_inputs(|| get_bench_args(&[]).into_iter()) + .bench_values(|args| black_box(uumain(args))); env::set_current_dir(original_dir).unwrap(); } @@ -41,6 +42,7 @@ fn df_deep_directory(bencher: Bencher) { #[divan::bench] fn df_with_path(bencher: Bencher) { use rustix::stdio::dup2_stdout; + use uucore::benchmark::run_util_function; let temp_dir = TempDir::new().unwrap(); let temp_path_str = temp_dir.path().to_str().unwrap(); @@ -62,11 +64,11 @@ fn df_with_path(bencher: Bencher) { #[divan::bench] fn df_with_path(bencher: Bencher) { let temp_dir = TempDir::new().unwrap(); - let temp_path_str = temp_dir.path().to_str().unwrap(); + let temp_path = temp_dir.path(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[temp_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&temp_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/du/benches/du_bench.rs b/src/uu/du/benches/du_bench.rs index 0b63ce9a2ac..39c58a3b261 100644 --- a/src/uu/du/benches/du_bench.rs +++ b/src/uu/du/benches/du_bench.rs @@ -6,18 +6,7 @@ use divan::{Bencher, black_box}; use tempfile::TempDir; use uu_du::uumain; -use uucore::benchmark::{fs_tree, run_util_function}; - -/// Helper to run du with given arguments on a directory -fn bench_du_with_args(bencher: Bencher, temp_dir: &TempDir, args: &[&str]) { - let temp_path_str = temp_dir.path().to_str().unwrap(); - let mut full_args = args.to_vec(); - full_args.push(temp_path_str); - - bencher.bench(|| { - black_box(run_util_function(uumain, &full_args)); - }); -} +use uucore::benchmark::{fs_tree, get_bench_args}; /* too much variance /// Benchmark default du on balanced tree @@ -27,8 +16,12 @@ fn du_balanced_tree( (depth, dirs_per_level, files_per_dir): (usize, usize, usize), ) { let temp_dir = TempDir::new().unwrap(); - fs_tree::create_balanced_tree(temp_dir.path(), depth, dirs_per_level, files_per_dir); - bench_du_with_args(bencher, &temp_dir, &[]); + let temp_path = temp_dir.path(); + fs_tree::create_balanced_tree(temp_path, depth, dirs_per_level, files_per_dir); + + bencher + .with_inputs(|| get_bench_args(&[&temp_path])) + .bench_values(|args| black_box(uumain(args))); } */ @@ -40,8 +33,12 @@ fn du_all_balanced_tree( (depth, dirs_per_level, files_per_dir): (usize, usize, usize), ) { let temp_dir = TempDir::new().unwrap(); - fs_tree::create_balanced_tree(temp_dir.path(), depth, dirs_per_level, files_per_dir); - bench_du_with_args(bencher, &temp_dir, &["-a"]); + let temp_path = temp_dir.path(); + fs_tree::create_balanced_tree(temp_path, depth, dirs_per_level, files_per_dir); + + bencher + .with_inputs(|| get_bench_args(&[&"-a", &temp_path])) + .bench_values(|args| black_box(uumain(args))); } */ @@ -53,57 +50,49 @@ fn du_human_balanced_tree( (depth, dirs_per_level, files_per_dir): (usize, usize, usize), ) { let temp_dir = TempDir::new().unwrap(); - fs_tree::create_balanced_tree(temp_dir.path(), depth, dirs_per_level, files_per_dir); - bench_du_with_args(bencher, &temp_dir, &["-h"]); + let temp_path = temp_dir.path(); + fs_tree::create_balanced_tree(temp_path, depth, dirs_per_level, files_per_dir); + + bencher + .with_inputs(|| get_bench_args(&[&"-h", &temp_path])) + .bench_values(|args| black_box(uumain(args))); } */ /// Benchmark du on wide directory structures (many files/dirs, shallow) #[divan::bench(args = [(5000, 500)])] fn du_wide_tree(bencher: Bencher, (total_files, total_dirs): (usize, usize)) { + let temp_dir = TempDir::new().unwrap(); + let temp_path = temp_dir.path(); + fs_tree::create_wide_tree(temp_path, total_files, total_dirs); + bencher - .with_inputs(|| { - let temp_dir = TempDir::new().unwrap(); - fs_tree::create_wide_tree(temp_dir.path(), total_files, total_dirs); - temp_dir - }) - .bench_values(|temp_dir| { - let temp_path_str = temp_dir.path().to_str().unwrap(); - let args = vec![temp_path_str]; - black_box(run_util_function(uumain, &args)); - }); + .with_inputs(|| get_bench_args(&[&temp_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark du -a on wide directory structures #[divan::bench(args = [(5000, 500)])] fn du_all_wide_tree(bencher: Bencher, (total_files, total_dirs): (usize, usize)) { + let temp_dir = TempDir::new().unwrap(); + let temp_path = temp_dir.path(); + fs_tree::create_wide_tree(temp_path, total_files, total_dirs); + bencher - .with_inputs(|| { - let temp_dir = TempDir::new().unwrap(); - fs_tree::create_wide_tree(temp_dir.path(), total_files, total_dirs); - temp_dir - }) - .bench_values(|temp_dir| { - let temp_path_str = temp_dir.path().to_str().unwrap(); - let args = vec![temp_path_str, "-a"]; - black_box(run_util_function(uumain, &args)); - }); + .with_inputs(|| get_bench_args(&[&"-a", &temp_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark du on deep directory structures #[divan::bench(args = [(100, 3)])] fn du_deep_tree(bencher: Bencher, (depth, files_per_level): (usize, usize)) { + let temp_dir = TempDir::new().unwrap(); + let temp_path = temp_dir.path(); + fs_tree::create_deep_tree(temp_path, depth, files_per_level); + bencher - .with_inputs(|| { - let temp_dir = TempDir::new().unwrap(); - fs_tree::create_deep_tree(temp_dir.path(), depth, files_per_level); - temp_dir - }) - .bench_values(|temp_dir| { - let temp_path_str = temp_dir.path().to_str().unwrap(); - let args = vec![temp_path_str]; - black_box(run_util_function(uumain, &args)); - }); + .with_inputs(|| get_bench_args(&[&temp_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark du -s (summarize) on balanced tree @@ -113,8 +102,12 @@ fn du_summarize_balanced_tree( (depth, dirs_per_level, files_per_dir): (usize, usize, usize), ) { let temp_dir = TempDir::new().unwrap(); - fs_tree::create_balanced_tree(temp_dir.path(), depth, dirs_per_level, files_per_dir); - bench_du_with_args(bencher, &temp_dir, &["-s"]); + let temp_path = temp_dir.path(); + fs_tree::create_balanced_tree(temp_path, depth, dirs_per_level, files_per_dir); + + bencher + .with_inputs(|| get_bench_args(&[&"-s", &temp_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark du with --max-depth @@ -124,8 +117,12 @@ fn du_max_depth_balanced_tree( (depth, dirs_per_level, files_per_dir): (usize, usize, usize), ) { let temp_dir = TempDir::new().unwrap(); - fs_tree::create_balanced_tree(temp_dir.path(), depth, dirs_per_level, files_per_dir); - bench_du_with_args(bencher, &temp_dir, &["--max-depth=2"]); + let temp_path = temp_dir.path(); + fs_tree::create_balanced_tree(temp_path, depth, dirs_per_level, files_per_dir); + + bencher + .with_inputs(|| get_bench_args(&[&"--max-depth=2", &temp_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/expand/benches/expand_bench.rs b/src/uu/expand/benches/expand_bench.rs index ff9c24ef15a..1fbe86e61a4 100644 --- a/src/uu/expand/benches/expand_bench.rs +++ b/src/uu/expand/benches/expand_bench.rs @@ -5,23 +5,9 @@ use divan::{Bencher, black_box}; use std::fmt::Write; +use tempfile::TempDir; use uu_expand::uumain; -use uucore::benchmark::{create_test_file, run_util_function}; - -/// Helper function to run expand benchmark with generated data -fn bench_expand(bencher: Bencher, data: impl AsRef<[u8]>, args: &[&str]) { - let temp_dir = tempfile::tempdir().unwrap(); - let file_path = create_test_file(data.as_ref(), temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - - let mut all_args = vec![]; - all_args.extend_from_slice(args); - all_args.push(file_path_str); - - bencher.bench(|| { - black_box(run_util_function(uumain, &all_args)); - }); -} +use uucore::benchmark::{create_test_file, get_bench_args}; /// Benchmark expanding tabs on files with many short lines #[divan::bench(args = [100_000])] @@ -30,7 +16,12 @@ fn expand_many_lines(bencher: Bencher, num_lines: usize) { writeln!(&mut acc, "line{i}\tvalue{}\tdata{}", i * 2, i * 3).unwrap(); acc }); - bench_expand(bencher, data, &[]); + let temp_dir = TempDir::new().unwrap(); + let file_path = create_test_file(data.as_ref(), temp_dir.path()); + + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark expanding tabs with custom tab stops @@ -40,7 +31,12 @@ fn expand_custom_tabstops(bencher: Bencher, num_lines: usize) { writeln!(&mut acc, "a\tb\tc\td\te{i}").unwrap(); acc }); - bench_expand(bencher, data, &["--tabs=4,8,12"]); + let temp_dir = TempDir::new().unwrap(); + let file_path = create_test_file(data.as_ref(), temp_dir.path()); + + bencher + .with_inputs(|| get_bench_args(&[&"--tabs=4,8,12", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/fold/benches/fold_bench.rs b/src/uu/fold/benches/fold_bench.rs index d76ddbeaf74..c4b0d969e54 100644 --- a/src/uu/fold/benches/fold_bench.rs +++ b/src/uu/fold/benches/fold_bench.rs @@ -4,43 +4,42 @@ // file that was distributed with this source code. use divan::{Bencher, black_box}; +use tempfile::TempDir; use uu_fold::uumain; -use uucore::benchmark::{create_test_file, run_util_function}; +use uucore::benchmark::{create_test_file, get_bench_args}; /// Benchmark folding many short lines #[divan::bench(args = [100_000])] fn fold_many_lines(bencher: Bencher, num_lines: usize) { - let temp_dir = tempfile::tempdir().unwrap(); let mut data = String::with_capacity(num_lines * 110); for i in 0..num_lines { data.push_str("This is a very long line number "); append_usize(&mut data, i); data.push_str(" that definitely needs to be folded at the default width of 80 columns\n"); } + let temp_dir = TempDir::new().unwrap(); let file_path = create_test_file(data.as_bytes(), temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark folding with custom width #[divan::bench(args = [50_000])] fn fold_custom_width(bencher: Bencher, num_lines: usize) { - let temp_dir = tempfile::tempdir().unwrap(); let mut data = String::with_capacity(num_lines * 80); for i in 0..num_lines { data.push_str("Line "); append_usize(&mut data, i); data.push_str(" with enough text to exceed width 40 characters and require folding\n"); } + let temp_dir = TempDir::new().unwrap(); let file_path = create_test_file(data.as_bytes(), temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-w", "40", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-w", &"40", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/seq/benches/seq_bench.rs b/src/uu/seq/benches/seq_bench.rs index 11956e8c04a..d4d559d5ff1 100644 --- a/src/uu/seq/benches/seq_bench.rs +++ b/src/uu/seq/benches/seq_bench.rs @@ -5,49 +5,46 @@ use divan::{Bencher, black_box}; use uu_seq::uumain; -use uucore::benchmark::run_util_function; +use uucore::benchmark::get_bench_args; /// Benchmark simple integer sequence #[divan::bench] fn seq_integers(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function(uumain, &["1", "1000000"])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"1", &"1000000"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark large integer #[divan::bench] fn seq_large_integers(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function(uumain, &["4e10003", "4e10003"])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"4e10003", &"4e10003"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sequence with custom separator #[divan::bench] fn seq_custom_separator(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function(uumain, &["-s", ",", "1", "1000000"])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-s", &",", &"1", &"1000000"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sequence with step #[divan::bench] fn seq_with_step(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function(uumain, &["1", "2", "1000000"])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"1", &"2", &"1000000"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark formatted output #[divan::bench] fn seq_formatted(bencher: Bencher) { - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-f", "%.3f", "1", "0.1", "10000"], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-f", &"%.3f", &"1", &"0.1", &"10000"]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/shuf/benches/shuf_bench.rs b/src/uu/shuf/benches/shuf_bench.rs index 62c3be0bad7..af37f09992a 100644 --- a/src/uu/shuf/benches/shuf_bench.rs +++ b/src/uu/shuf/benches/shuf_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_shuf::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; /// Benchmark shuffling lines from a file /// Tests the default mode with a large number of lines @@ -13,11 +13,10 @@ use uucore::benchmark::{run_util_function, setup_test_file, text_data}; fn shuf_lines(bencher: Bencher, num_lines: usize) { let data = text_data::generate_by_lines(num_lines, 80); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark shuffling a numeric range with -i @@ -26,9 +25,9 @@ fn shuf_lines(bencher: Bencher, num_lines: usize) { fn shuf_input_range(bencher: Bencher, range_size: usize) { let range_arg = format!("1-{range_size}"); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-i", &range_arg])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-i", &range_arg]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark shuffling with repeat (sampling with replacement) @@ -37,15 +36,11 @@ fn shuf_input_range(bencher: Bencher, range_size: usize) { fn shuf_repeat_sampling(bencher: Bencher, num_lines: usize) { let data = text_data::generate_by_lines(10_000, 80); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); let count = format!("{num_lines}"); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-r", "-n", &count, file_path_str], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-r", &"-n", &count, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/sort/benches/sort_bench.rs b/src/uu/sort/benches/sort_bench.rs index 08a23b65602..ef6d6a0a925 100644 --- a/src/uu/sort/benches/sort_bench.rs +++ b/src/uu/sort/benches/sort_bench.rs @@ -6,7 +6,7 @@ use divan::{Bencher, black_box}; use tempfile::NamedTempFile; use uu_sort::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; /// Benchmark sorting ASCII-only data #[divan::bench(args = [500_000])] @@ -14,14 +14,11 @@ fn sort_ascii_only(bencher: Bencher, num_lines: usize) { let data = text_data::generate_ascii_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sorting accented/non-ASCII data @@ -30,14 +27,11 @@ fn sort_accented_data(bencher: Bencher, num_lines: usize) { let data = text_data::generate_accented_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sorting mixed ASCII/non-ASCII data @@ -46,14 +40,11 @@ fn sort_mixed_data(bencher: Bencher, num_lines: usize) { let data = text_data::generate_mixed_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark case-sensitive sorting with mixed case data @@ -62,14 +53,11 @@ fn sort_case_sensitive(bencher: Bencher, num_lines: usize) { let data = text_data::generate_case_sensitive_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark case-insensitive sorting (fold case) @@ -78,14 +66,11 @@ fn sort_case_insensitive(bencher: Bencher, num_lines: usize) { let data = text_data::generate_case_sensitive_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-f", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-f", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark dictionary order sorting (only blanks and alphanumeric) @@ -94,14 +79,11 @@ fn sort_dictionary_order(bencher: Bencher, num_lines: usize) { let data = text_data::generate_mixed_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-d", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-d", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark numeric sorting with mixed data @@ -118,14 +100,11 @@ fn sort_numeric(bencher: Bencher, num_lines: usize) { let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-n", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-n", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark general numeric sorting (-g) with decimal and exponent notation @@ -146,12 +125,9 @@ fn sort_general_numeric(bencher: Bencher, num_lines: usize) { let output_file = NamedTempFile::new().unwrap(); let output_path = output_file.path().to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-g", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-g", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark reverse sorting with locale-aware data @@ -160,14 +136,11 @@ fn sort_reverse_locale(bencher: Bencher, num_lines: usize) { let data = text_data::generate_accented_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-r", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-r", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sorting with specific key field @@ -187,15 +160,12 @@ fn sort_key_field(bencher: Bencher, num_lines: usize) { let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { + bencher // Sort by second field - black_box(run_util_function( - uumain, - &["-k", "2", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + .with_inputs(|| get_bench_args(&[&"-k", &"2", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark unique sorting with locale-aware data @@ -204,14 +174,11 @@ fn sort_unique_locale(bencher: Bencher, num_lines: usize) { let data = text_data::generate_accented_data(num_lines); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-u", "-o", output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-u", &"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sorting with very long lines exceeding `DEFAULT_BUF_SIZE` (8192 bytes) @@ -227,19 +194,11 @@ fn sort_long_line(bencher: Bencher, line_size: usize) { let file_a = setup_test_file(&data_a); let file_b = setup_test_file(&data_b); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &[ - file_a.to_str().unwrap(), - file_b.to_str().unwrap(), - "-o", - output_path, - ], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_a, &file_b, &"-o", &output_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/sort/benches/sort_locale_c_bench.rs b/src/uu/sort/benches/sort_locale_c_bench.rs index 8335992716c..4a5cbcfdb06 100644 --- a/src/uu/sort/benches/sort_locale_c_bench.rs +++ b/src/uu/sort/benches/sort_locale_c_bench.rs @@ -11,7 +11,7 @@ use divan::{Bencher, black_box}; use tempfile::NamedTempFile; use uu_sort::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; /// Benchmark ASCII-only data sorting with C locale (byte comparison) #[divan::bench] @@ -19,14 +19,11 @@ fn sort_ascii_c_locale(bencher: Bencher) { let data = text_data::generate_ascii_data_simple(2_000_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", &output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark mixed ASCII/Unicode data with C locale (byte comparison) @@ -35,14 +32,11 @@ fn sort_mixed_c_locale(bencher: Bencher) { let data = text_data::generate_mixed_locale_data(50_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", &output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark German locale-specific data with C locale (byte comparison) @@ -51,14 +45,11 @@ fn sort_german_c_locale(bencher: Bencher) { let data = text_data::generate_german_locale_data(50_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", &output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/sort/benches/sort_locale_de_bench.rs b/src/uu/sort/benches/sort_locale_de_bench.rs index 5c760a694e8..a2236a955d7 100644 --- a/src/uu/sort/benches/sort_locale_de_bench.rs +++ b/src/uu/sort/benches/sort_locale_de_bench.rs @@ -11,7 +11,7 @@ use divan::{Bencher, black_box}; use tempfile::NamedTempFile; use uu_sort::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; /// Benchmark German locale-specific data with German locale #[divan::bench] @@ -19,14 +19,11 @@ fn sort_german_de_locale(bencher: Bencher) { let data = text_data::generate_german_locale_data(50_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - bencher.bench(|| { - black_box(run_util_function( - uumain, - &["-o", &output_path, file_path.to_str().unwrap()], - )); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-o", &output_path, &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/sort/benches/sort_locale_utf8_bench.rs b/src/uu/sort/benches/sort_locale_utf8_bench.rs index 81e39c8971f..fdef7896815 100644 --- a/src/uu/sort/benches/sort_locale_utf8_bench.rs +++ b/src/uu/sort/benches/sort_locale_utf8_bench.rs @@ -11,7 +11,7 @@ use divan::{Bencher, black_box}; use tempfile::NamedTempFile; use uu_sort::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, run_util_function, setup_test_file, text_data}; /// Benchmark ASCII-only data sorting with UTF-8 locale #[divan::bench] @@ -19,13 +19,13 @@ fn sort_ascii_utf8_locale(bencher: Bencher) { let data = text_data::generate_ascii_data_simple(1_500_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - let args = ["-o", &output_path, file_path.to_str().unwrap()]; - black_box(run_util_function(uumain, &args)); - bencher.bench(|| { - black_box(run_util_function(uumain, &args)); - }); + let args = get_bench_args(&[&"-o", &output_path, &file_path]); + black_box(uumain(args.clone().into_iter())); + bencher + .with_inputs(|| args.clone().into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark mixed ASCII/Unicode data with UTF-8 locale @@ -34,13 +34,13 @@ fn sort_mixed_utf8_locale(bencher: Bencher) { let data = text_data::generate_mixed_locale_data(50_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - let args = ["-o", &output_path, file_path.to_str().unwrap()]; - black_box(run_util_function(uumain, &args)); - bencher.bench(|| { - black_box(run_util_function(uumain, &args)); - }); + let args = get_bench_args(&[&"-o", &output_path, &file_path]); + black_box(uumain(args.clone().into_iter())); + bencher + .with_inputs(|| args.clone().into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark numeric sorting with UTF-8 locale @@ -53,13 +53,13 @@ fn sort_numeric_utf8_locale(bencher: Bencher) { } let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - let args = ["-n", "-o", &output_path, file_path.to_str().unwrap()]; - black_box(run_util_function(uumain, &args)); - bencher.bench(|| { - black_box(run_util_function(uumain, &args)); - }); + let args = get_bench_args(&[&"-n", &"-o", &output_path, &file_path]); + black_box(uumain(args.clone().into_iter())); + bencher + .with_inputs(|| args.clone().into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark reverse sorting with UTF-8 locale @@ -68,13 +68,13 @@ fn sort_reverse_utf8_locale(bencher: Bencher) { let data = text_data::generate_mixed_locale_data(50_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - let args = ["-r", "-o", &output_path, file_path.to_str().unwrap()]; - black_box(run_util_function(uumain, &args)); - bencher.bench(|| { - black_box(run_util_function(uumain, &args)); - }); + let args = get_bench_args(&[&"-r", &"-o", &output_path, &file_path]); + black_box(uumain(args.clone().into_iter())); + bencher + .with_inputs(|| args.clone().into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark unique sorting with UTF-8 locale @@ -83,13 +83,13 @@ fn sort_unique_utf8_locale(bencher: Bencher) { let data = text_data::generate_mixed_locale_data(50_000); let file_path = setup_test_file(&data); let output_file = NamedTempFile::new().unwrap(); - let output_path = output_file.path().to_str().unwrap().to_string(); + let output_path = output_file.path(); - let args = ["-u", "-o", &output_path, file_path.to_str().unwrap()]; - black_box(run_util_function(uumain, &args)); - bencher.bench(|| { - black_box(run_util_function(uumain, &args)); - }); + let args = get_bench_args(&[&"-u", &"-o", &output_path, &file_path]); + black_box(uumain(args.clone().into_iter())); + bencher + .with_inputs(|| args.clone().into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark sorting very long lines (single repeated character per line) with UTF-8 locale. diff --git a/src/uu/split/benches/split_bench.rs b/src/uu/split/benches/split_bench.rs index d09d658b01d..7c3cfea5856 100644 --- a/src/uu/split/benches/split_bench.rs +++ b/src/uu/split/benches/split_bench.rs @@ -6,7 +6,7 @@ use divan::{Bencher, black_box}; use tempfile::TempDir; use uu_split::uumain; -use uucore::benchmark::{run_util_function, setup_test_file, text_data}; +use uucore::benchmark::{get_bench_args, setup_test_file, text_data}; /// Benchmark splitting by line count #[divan::bench] @@ -18,13 +18,11 @@ fn split_lines(bencher: Bencher) { .with_inputs(|| { let output_dir = TempDir::new().unwrap(); let prefix = output_dir.path().join("x"); - (output_dir, prefix.to_str().unwrap().to_string()) + let args = get_bench_args(&[&"-l", &"1000", &file_path, &prefix]).into_iter(); + (output_dir, args) }) - .bench_values(|(output_dir, prefix)| { - black_box(run_util_function( - uumain, - &["-l", "1000", file_path.to_str().unwrap(), &prefix], - )); + .bench_values(|(output_dir, args)| { + black_box(uumain(args)); drop(output_dir); }); } @@ -39,13 +37,11 @@ fn split_bytes(bencher: Bencher) { .with_inputs(|| { let output_dir = TempDir::new().unwrap(); let prefix = output_dir.path().join("x"); - (output_dir, prefix.to_str().unwrap().to_string()) + let args = get_bench_args(&[&"-b", &"100K", &file_path, &prefix]).into_iter(); + (output_dir, args) }) - .bench_values(|(output_dir, prefix)| { - black_box(run_util_function( - uumain, - &["-b", "100K", file_path.to_str().unwrap(), &prefix], - )); + .bench_values(|(output_dir, args)| { + black_box(uumain(args)); drop(output_dir); }); } @@ -60,13 +56,11 @@ fn split_number_chunks(bencher: Bencher) { .with_inputs(|| { let output_dir = TempDir::new().unwrap(); let prefix = output_dir.path().join("x"); - (output_dir, prefix.to_str().unwrap().to_string()) + let args = get_bench_args(&[&"-n", &"10", &file_path, &prefix]).into_iter(); + (output_dir, args) }) - .bench_values(|(output_dir, prefix)| { - black_box(run_util_function( - uumain, - &["-n", "10", file_path.to_str().unwrap(), &prefix], - )); + .bench_values(|(output_dir, args)| { + black_box(uumain(args)); drop(output_dir); }); } @@ -81,13 +75,11 @@ fn split_numeric_suffix(bencher: Bencher) { .with_inputs(|| { let output_dir = TempDir::new().unwrap(); let prefix = output_dir.path().join("x"); - (output_dir, prefix.to_str().unwrap().to_string()) + let args = get_bench_args(&[&"-d", &"-l", &"500", &file_path, &prefix]).into_iter(); + (output_dir, args) }) - .bench_values(|(output_dir, prefix)| { - black_box(run_util_function( - uumain, - &["-d", "-l", "500", file_path.to_str().unwrap(), &prefix], - )); + .bench_values(|(output_dir, args)| { + black_box(uumain(args)); drop(output_dir); }); } diff --git a/src/uu/tsort/benches/tsort_bench.rs b/src/uu/tsort/benches/tsort_bench.rs index 28395cffd0e..854340fea07 100644 --- a/src/uu/tsort/benches/tsort_bench.rs +++ b/src/uu/tsort/benches/tsort_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_tsort::uumain; -use uucore::benchmark::{run_util_function, setup_test_file}; +use uucore::benchmark::{get_bench_args, setup_test_file}; /// Generate topological sort test data - linear chain fn generate_linear_chain(num_nodes: usize) -> Vec { @@ -118,11 +118,10 @@ fn generate_wide_dag(num_nodes: usize) -> Vec { fn tsort_linear_chain(bencher: Bencher, num_nodes: usize) { let data = generate_linear_chain(num_nodes); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark tree-like DAG structures @@ -130,11 +129,10 @@ fn tsort_linear_chain(bencher: Bencher, num_nodes: usize) { fn tsort_tree_dag(bencher: Bencher, (depth, branching): (usize, usize)) { let data = generate_tree_dag(depth, branching); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark complex DAG with cross-dependencies @@ -142,11 +140,10 @@ fn tsort_tree_dag(bencher: Bencher, (depth, branching): (usize, usize)) { fn tsort_complex_dag(bencher: Bencher, num_nodes: usize) { let data = generate_complex_dag(num_nodes); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark wide DAG with many parallel chains @@ -155,11 +152,10 @@ fn tsort_complex_dag(bencher: Bencher, num_nodes: usize) { fn tsort_wide_dag(bencher: Bencher, num_nodes: usize) { let data = generate_wide_dag(num_nodes); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /* @@ -189,11 +185,10 @@ fn generate_input_parsing_heavy(num_edges: usize) -> Vec { fn tsort_input_parsing_heavy(bencher: Bencher, num_edges: usize) { let data = generate_input_parsing_heavy(num_edges); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path])) + .bench_values(|args| black_box(uumain(args))); } */ diff --git a/src/uu/unexpand/benches/unexpand_bench.rs b/src/uu/unexpand/benches/unexpand_bench.rs index 1f9c19469c7..8d2e29f0d48 100644 --- a/src/uu/unexpand/benches/unexpand_bench.rs +++ b/src/uu/unexpand/benches/unexpand_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_unexpand::uumain; -use uucore::benchmark::{create_test_file, run_util_function}; +use uucore::benchmark::{create_test_file, get_bench_args}; /// Generate text data with leading spaces (typical unexpand use case) fn generate_indented_text(num_lines: usize) -> Vec { @@ -25,11 +25,10 @@ fn unexpand_many_lines(bencher: Bencher, num_lines: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = generate_indented_text(num_lines); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark large file with spaces (tests performance on large files) @@ -42,11 +41,10 @@ fn unexpand_large_file(bencher: Bencher, size_mb: usize) { let num_lines = (size_mb * 1024 * 1024) / line_size; let data = generate_indented_text(num_lines); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uu/uniq/benches/uniq_bench.rs b/src/uu/uniq/benches/uniq_bench.rs index 780ecff154c..5f405baa69b 100644 --- a/src/uu/uniq/benches/uniq_bench.rs +++ b/src/uu/uniq/benches/uniq_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_uniq::uumain; -use uucore::benchmark::{run_util_function, setup_test_file}; +use uucore::benchmark::{get_bench_args, run_util_function, setup_test_file}; /// Generate data with many consecutive duplicate lines /// This directly tests the core optimization of PR #8703 - avoiding allocations when comparing lines @@ -37,11 +37,10 @@ fn uniq_heavy_duplicates(bencher: Bencher, num_lines: usize) { let duplicates_per_group = num_lines / num_groups; let data = generate_duplicate_heavy_data(num_groups, duplicates_per_group); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &[file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark 2: Mixed duplicates with counting @@ -52,11 +51,10 @@ fn uniq_with_count(bencher: Bencher, num_lines: usize) { let num_groups = num_lines / 100; let data = generate_duplicate_heavy_data(num_groups, 100); let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-c", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-c", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark 3: Case-insensitive comparison with duplicates @@ -101,11 +99,10 @@ fn uniq_case_insensitive(bencher: Bencher, num_lines: usize) { } let file_path = setup_test_file(&data); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-i", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-i", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark 4: `-w N` over duplicate-heavy input, for both a narrow N (1) diff --git a/src/uu/wc/benches/wc_bench.rs b/src/uu/wc/benches/wc_bench.rs index 79f8fbd2fea..6abcb5efd4a 100644 --- a/src/uu/wc/benches/wc_bench.rs +++ b/src/uu/wc/benches/wc_bench.rs @@ -5,7 +5,7 @@ use divan::{Bencher, black_box}; use uu_wc::uumain; -use uucore::benchmark::{create_test_file, run_util_function, text_data}; +use uucore::benchmark::{create_test_file, get_bench_args, text_data}; /// Benchmark different file sizes for byte counting #[divan::bench(args = [1, 500])] //todo: add 10kb to measure splice() overhead @@ -13,11 +13,10 @@ fn wc_bytes_synthetic(bencher: Bencher, size_mb: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_size(size_mb, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-c", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-c", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } #[divan::bench(args = [2_000])] @@ -25,11 +24,10 @@ fn wc_words_synthetic(bencher: Bencher, size_mb: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_size(size_mb, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-w", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-w", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark combined byte+line counting @@ -38,11 +36,10 @@ fn wc_bytes_lines_synthetic(bencher: Bencher, size_mb: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_size(size_mb, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-cl", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-cl", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Test different line lengths impact on performance @@ -51,11 +48,10 @@ fn wc_lines_variable_length(bencher: Bencher, (size_mb, avg_line_len): (usize, u let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_size(size_mb, avg_line_len); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-l", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-l", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark large files by line count - up to 500K lines! @@ -64,11 +60,10 @@ fn wc_lines_large_line_count(bencher: Bencher, num_lines: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_lines(num_lines, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-l", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-l", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark character counting on large line counts @@ -77,11 +72,10 @@ fn wc_chars_large_line_count(bencher: Bencher, num_lines: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_lines(num_lines, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-m", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-m", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark word counting on large line counts @@ -90,11 +84,10 @@ fn wc_words_large_line_count(bencher: Bencher, num_lines: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_lines(num_lines, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-w", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-w", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark default wc (lines, words, bytes) on large line counts @@ -103,11 +96,10 @@ fn wc_default_large_line_count(bencher: Bencher, num_lines: usize) { let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_lines(num_lines, 80); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-lwc", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-lwc", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } /// Benchmark very short vs very long lines with 100K lines @@ -116,11 +108,10 @@ fn wc_lines_extreme_line_lengths(bencher: Bencher, (num_lines, line_len): (usize let temp_dir = tempfile::tempdir().unwrap(); let data = text_data::generate_by_lines(num_lines, line_len); let file_path = create_test_file(&data, temp_dir.path()); - let file_path_str = file_path.to_str().unwrap(); - bencher.bench(|| { - black_box(run_util_function(uumain, &["-l", file_path_str])); - }); + bencher + .with_inputs(|| get_bench_args(&[&"-l", &file_path]).into_iter()) + .bench_values(|args| black_box(uumain(args))); } fn main() { diff --git a/src/uucore/src/lib/features/benchmark.rs b/src/uucore/src/lib/features/benchmark.rs index e2dfac1e72a..c14760e4f64 100644 --- a/src/uucore/src/lib/features/benchmark.rs +++ b/src/uucore/src/lib/features/benchmark.rs @@ -40,6 +40,14 @@ where util_func(os_args.into_iter()) } +/// Prepare benchmark arguments for a utility function +pub fn get_bench_args(args: &[&dyn AsRef]) -> Vec { + // Prepend a dummy program name as argv[0] since clap expects it + std::iter::once("benchmark".into()) + .chain(args.iter().map(Into::into)) + .collect_vec() +} + /// Helper function to set up a temporary test file and leak the temporary directory /// so it persists for the duration of the benchmark pub fn setup_test_file(data: &[u8]) -> PathBuf {