From 710cdb2abff0e8bb7bf742632b8c053ef9b9d3f5 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 10 Oct 2025 23:13:03 +0200 Subject: [PATCH] mv: add benchmarks --- src/uu/mv/Cargo.toml | 9 +++ src/uu/mv/benches/mv_bench.rs | 120 ++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/uu/mv/benches/mv_bench.rs diff --git a/src/uu/mv/Cargo.toml b/src/uu/mv/Cargo.toml index 329bb78ba..0ed038fe6 100644 --- a/src/uu/mv/Cargo.toml +++ b/src/uu/mv/Cargo.toml @@ -47,3 +47,12 @@ selinux = ["uucore/selinux"] [[bin]] name = "mv" path = "src/main.rs" + +[dev-dependencies] +divan = { workspace = true } +tempfile = { workspace = true } +uucore = { workspace = true, features = ["benchmark"] } + +[[bench]] +name = "mv_bench" +harness = false diff --git a/src/uu/mv/benches/mv_bench.rs b/src/uu/mv/benches/mv_bench.rs new file mode 100644 index 000000000..80c5500fb --- /dev/null +++ b/src/uu/mv/benches/mv_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_mv::uumain; +use uucore::benchmark::{fs_tree, run_util_function}; + +/// Benchmark moving a single file (repeated to reach 100ms) +#[divan::bench] +fn mv_single_file(bencher: Bencher) { + bencher + .with_inputs(|| { + let temp_dir = TempDir::new().unwrap(); + fs_tree::create_wide_tree(temp_dir.path(), 1000, 0); + let files: Vec<(String, String)> = (0..1000) + .map(|i| { + let src = temp_dir.path().join(format!("f{i}")); + let dst = temp_dir.path().join(format!("moved_{i}")); + ( + src.to_str().unwrap().to_string(), + dst.to_str().unwrap().to_string(), + ) + }) + .collect(); + (temp_dir, files) + }) + .bench_values(|(temp_dir, files)| { + for (src, dst) in &files { + black_box(run_util_function(uumain, &[src, dst])); + } + drop(temp_dir); + }); +} + +/// Benchmark moving multiple files to directory +#[divan::bench] +fn mv_multiple_to_dir(bencher: Bencher) { + bencher + .with_inputs(|| { + let temp_dir = TempDir::new().unwrap(); + fs_tree::create_wide_tree(temp_dir.path(), 1000, 0); + let dest_dir = temp_dir.path().join("dest"); + std::fs::create_dir(&dest_dir).unwrap(); + + let mut args: Vec = (0..1000) + .map(|i| { + temp_dir + .path() + .join(format!("f{i}")) + .to_str() + .unwrap() + .to_string() + }) + .collect(); + args.push(dest_dir.to_str().unwrap().to_string()); + (temp_dir, args) + }) + .bench_values(|(temp_dir, args)| { + let arg_refs: Vec<&str> = args.iter().map(|s| s.as_str()).collect(); + black_box(run_util_function(uumain, &arg_refs)); + drop(temp_dir); + }); +} + +/// Benchmark moving directory recursively +#[divan::bench] +fn mv_directory(bencher: Bencher) { + bencher + .with_inputs(|| { + let temp_dir = TempDir::new().unwrap(); + let src_dir = temp_dir.path().join("src_tree"); + std::fs::create_dir(&src_dir).unwrap(); + // Increase tree size for longer benchmark + fs_tree::create_balanced_tree(&src_dir, 5, 5, 10); + let dst_dir = temp_dir.path().join("dest_tree"); + ( + temp_dir, + src_dir.to_str().unwrap().to_string(), + dst_dir.to_str().unwrap().to_string(), + ) + }) + .bench_values(|(temp_dir, src, dst)| { + black_box(run_util_function(uumain, &[&src, &dst])); + drop(temp_dir); + }); +} + +/// Benchmark force overwrite +#[divan::bench] +fn mv_force_overwrite(bencher: Bencher) { + bencher + .with_inputs(|| { + let temp_dir = TempDir::new().unwrap(); + fs_tree::create_wide_tree(temp_dir.path(), 2000, 0); + let files: Vec<(String, String)> = (0..1000) + .map(|i| { + let src = temp_dir.path().join(format!("f{i}")); + let dst = temp_dir.path().join(format!("f{}", i + 1000)); + ( + src.to_str().unwrap().to_string(), + dst.to_str().unwrap().to_string(), + ) + }) + .collect(); + (temp_dir, files) + }) + .bench_values(|(temp_dir, files)| { + for (src, dst) in &files { + black_box(run_util_function(uumain, &["-f", src, dst])); + } + drop(temp_dir); + }); +} + +fn main() { + divan::main(); +}