diff --git a/src/uu/cp/benches/cp_bench.rs b/src/uu/cp/benches/cp_bench.rs index ba29596d93c..d673c14e48c 100644 --- a/src/uu/cp/benches/cp_bench.rs +++ b/src/uu/cp/benches/cp_bench.rs @@ -4,24 +4,11 @@ // file that was distributed with this source code. use divan::{Bencher, black_box}; -use std::fs::{self, File}; -use std::io::Write; +use std::fs; use std::path::Path; use tempfile::TempDir; use uu_cp::uumain; -use uucore::benchmark::{fs_tree, run_util_function}; - -fn remove_path(path: &Path) { - if !path.exists() { - return; - } - - if path.is_dir() { - fs::remove_dir_all(path).unwrap(); - } else { - fs::remove_file(path).unwrap(); - } -} +use uucore::benchmark::{binary_data, fs_tree, fs_utils, run_util_function}; fn bench_cp_directory(bencher: Bencher, args: &[&str], setup_source: F) where @@ -38,7 +25,7 @@ where let dest_str = dest.to_str().unwrap(); bencher.bench(|| { - remove_path(&dest); + fs_utils::remove_path(&dest); let mut full_args = Vec::with_capacity(args.len() + 2); full_args.extend_from_slice(args); @@ -99,16 +86,13 @@ fn cp_large_file(bencher: Bencher, size_mb: usize) { let source = temp_dir.path().join("source.bin"); let dest = temp_dir.path().join("dest.bin"); - let buffer = vec![b'x'; size_mb * 1024 * 1024]; - let mut file = File::create(&source).unwrap(); - file.write_all(&buffer).unwrap(); - file.sync_all().unwrap(); + binary_data::create_file(&source, size_mb, b'x'); let source_str = source.to_str().unwrap(); let dest_str = dest.to_str().unwrap(); bencher.bench(|| { - remove_path(&dest); + fs_utils::remove_path(&dest); black_box(run_util_function(uumain, &[source_str, dest_str])); }); diff --git a/src/uu/dd/benches/dd_bench.rs b/src/uu/dd/benches/dd_bench.rs index 0a86f5de18b..b08207e7ecc 100644 --- a/src/uu/dd/benches/dd_bench.rs +++ b/src/uu/dd/benches/dd_bench.rs @@ -4,40 +4,25 @@ // file that was distributed with this source code. use divan::{Bencher, black_box}; -use std::fs::{self, File}; -use std::io::Write; -use std::path::Path; use tempfile::TempDir; use uu_dd::uumain; -use uucore::benchmark::run_util_function; - -fn create_test_file(path: &Path, size_mb: usize) { - let buffer = vec![b'x'; size_mb * 1024 * 1024]; - let mut file = File::create(path).unwrap(); - file.write_all(&buffer).unwrap(); - file.sync_all().unwrap(); -} - -fn remove_file(path: &Path) { - if path.exists() { - fs::remove_file(path).unwrap(); - } -} +use uucore::benchmark::{binary_data, fs_utils, run_util_function}; /// Benchmark basic dd copy with default settings -#[divan::bench(args = [32])] -fn dd_copy_default(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_default(bencher: Bencher) { + let size_mb = 32; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -50,19 +35,20 @@ fn dd_copy_default(bencher: Bencher, size_mb: usize) { } /// Benchmark dd copy with 4KB block size (common page size) -#[divan::bench(args = [24])] -fn dd_copy_4k_blocks(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_4k_blocks(bencher: Bencher) { + let size_mb = 24; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -76,19 +62,20 @@ fn dd_copy_4k_blocks(bencher: Bencher, size_mb: usize) { } /// Benchmark dd copy with 64KB block size -#[divan::bench(args = [64])] -fn dd_copy_64k_blocks(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_64k_blocks(bencher: Bencher) { + let size_mb = 64; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -102,19 +89,20 @@ fn dd_copy_64k_blocks(bencher: Bencher, size_mb: usize) { } /// Benchmark dd copy with 1MB block size -#[divan::bench(args = [128])] -fn dd_copy_1m_blocks(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_1m_blocks(bencher: Bencher) { + let size_mb = 128; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -128,19 +116,20 @@ fn dd_copy_1m_blocks(bencher: Bencher, size_mb: usize) { } /// Benchmark dd copy with separate input and output block sizes -#[divan::bench(args = [48])] -fn dd_copy_separate_blocks(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_separate_blocks(bencher: Bencher) { + let size_mb = 48; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -155,19 +144,20 @@ fn dd_copy_separate_blocks(bencher: Bencher, size_mb: usize) { } /// Benchmark dd with count limit (partial copy) -#[divan::bench(args = [32])] -fn dd_copy_partial(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_partial(bencher: Bencher) { + let size_mb = 32; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -182,19 +172,20 @@ fn dd_copy_partial(bencher: Bencher, size_mb: usize) { } /// Benchmark dd with skip (seeking in input) -#[divan::bench(args = [48])] -fn dd_copy_with_skip(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_with_skip(bencher: Bencher) { + let size_mb = 48; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -209,19 +200,20 @@ fn dd_copy_with_skip(bencher: Bencher, size_mb: usize) { } /// Benchmark dd with seek (seeking in output) -#[divan::bench(args = [48])] -fn dd_copy_with_seek(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_with_seek(bencher: Bencher) { + let size_mb = 48; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ @@ -236,19 +228,20 @@ fn dd_copy_with_seek(bencher: Bencher, size_mb: usize) { } /// Benchmark dd with different block sizes for comparison -#[divan::bench(args = [32])] -fn dd_copy_8k_blocks(bencher: Bencher, size_mb: usize) { +#[divan::bench] +fn dd_copy_8k_blocks(bencher: Bencher) { + let size_mb = 32; let temp_dir = TempDir::new().unwrap(); let input = temp_dir.path().join("input.bin"); let output = temp_dir.path().join("output.bin"); - create_test_file(&input, size_mb); + binary_data::create_file(&input, size_mb, b'x'); let input_str = input.to_str().unwrap(); let output_str = output.to_str().unwrap(); bencher.bench(|| { - remove_file(&output); + fs_utils::remove_path(&output); black_box(run_util_function( uumain, &[ diff --git a/src/uucore/src/lib/features/benchmark.rs b/src/uucore/src/lib/features/benchmark.rs index 306ffdc3da7..8be0baf720a 100644 --- a/src/uucore/src/lib/features/benchmark.rs +++ b/src/uucore/src/lib/features/benchmark.rs @@ -289,6 +289,46 @@ pub mod text_data { } } +/// Binary data generation utilities for benchmarking +pub mod binary_data { + use std::fs::File; + use std::io::Write; + use std::path::Path; + + /// Create a binary file filled with a repeated pattern + /// + /// Creates a file of the specified size (in MB) filled with the given byte pattern. + /// This is useful for benchmarking utilities that work with large binary files like dd, cp, etc. + pub fn create_file(path: &Path, size_mb: usize, pattern: u8) { + let buffer = vec![pattern; size_mb * 1024 * 1024]; + let mut file = File::create(path).unwrap(); + file.write_all(&buffer).unwrap(); + file.sync_all().unwrap(); + } +} + +/// Filesystem utilities for benchmarking +pub mod fs_utils { + use std::fs; + use std::path::Path; + + /// Remove a file or directory if it exists + /// + /// This is a convenience function for cleaning up between benchmark iterations. + /// It handles both files and directories, and is a no-op if the path doesn't exist. + pub fn remove_path(path: &Path) { + if !path.exists() { + return; + } + + if path.is_dir() { + fs::remove_dir_all(path).unwrap(); + } else { + fs::remove_file(path).unwrap(); + } + } +} + /// Filesystem tree generation utilities for benchmarking pub mod fs_tree { use std::fs::{self, File};