From 7bee7b47decd7eaa9be203e0f2161bfa13427216 Mon Sep 17 00:00:00 2001 From: naoNao89 <90588855+naoNao89@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:20:34 +0700 Subject: [PATCH 1/4] bench: add cksum performance benchmarks - Add comprehensive benchmarks for all 17 SUPPORTED_ALGORITHMS - Include custom SHAKE algorithm benchmarks using direct digest calculation - Add CI integration with benchmark workflow - No core cksum logic modifications to avoid merge conflicts --- .github/workflows/benchmarks.yml | 1 + Cargo.lock | 2 + src/uu/cksum/Cargo.toml | 9 ++ src/uu/cksum/benches/cksum_bench.rs | 146 ++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 src/uu/cksum/benches/cksum_bench.rs diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 9051f70ab4b..7485555e0cb 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -24,6 +24,7 @@ jobs: matrix: benchmark-target: - { package: uu_base64 } + - { package: uu_cksum } - { package: uu_cp } - { package: uu_cut } - { package: uu_du } diff --git a/Cargo.lock b/Cargo.lock index b3e0a507130..0e8a6ed88b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3259,8 +3259,10 @@ name = "uu_cksum" version = "0.3.0" dependencies = [ "clap", + "codspeed-divan-compat", "fluent", "hex", + "tempfile", "uucore", ] diff --git a/src/uu/cksum/Cargo.toml b/src/uu/cksum/Cargo.toml index 0eb4d28541d..01ca5cb16b5 100644 --- a/src/uu/cksum/Cargo.toml +++ b/src/uu/cksum/Cargo.toml @@ -23,6 +23,15 @@ uucore = { workspace = true, features = ["checksum", "encoding", "sum"] } hex = { workspace = true } fluent = { workspace = true } +[dev-dependencies] +divan = { workspace = true } +tempfile = { workspace = true } +uucore = { workspace = true, features = ["benchmark"] } + [[bin]] name = "cksum" path = "src/main.rs" + +[[bench]] +name = "cksum_bench" +harness = false diff --git a/src/uu/cksum/benches/cksum_bench.rs b/src/uu/cksum/benches/cksum_bench.rs new file mode 100644 index 00000000000..9c38042a91c --- /dev/null +++ b/src/uu/cksum/benches/cksum_bench.rs @@ -0,0 +1,146 @@ +// 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_cksum::uumain; +use uucore::benchmark::{run_util_function, setup_test_file, text_data}; + +// Macro to generate benchmarks for each algorithm +macro_rules! bench_algorithm { + ($algo_name:ident, $algo_str:expr) => { + #[divan::bench] + fn $algo_name(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, + &["--algorithm", $algo_str, file_path.to_str().unwrap()], + )); + }); + } + }; + ($algo_name:ident, $algo_str:expr, length) => { + #[divan::bench] + fn $algo_name(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, + &[ + "--algorithm", + $algo_str, + "--length", + "1048576", + file_path.to_str().unwrap(), + ], + )); + }); + } + }; +} + +// Special macro for SHAKE algorithms that require length parameter +// Since SHAKE algorithms have fundamental --length parameter conflicts in cksum, +// we implement them using direct digest calculation for meaningful benchmarks +macro_rules! bench_shake_algorithm { + ($algo_name:ident, $algo_str:expr, $shake_type:ty) => { + #[divan::bench] + fn $algo_name(bencher: Bencher) { + use uucore::sum::{Digest, Shake128, Shake256}; + + let data = text_data::generate_by_size(100, 80); + + bencher.bench(|| { + let mut shake = <$shake_type>::new(); + shake.hash_update(&data); + + // SHAKE algorithms can output any length, use 256 bits (32 bytes) for meaningful comparison + let mut output = [0u8; 32]; + shake.hash_finalize(&mut output); + + black_box(output); + }); + } + }; +} + +// Generate benchmarks for all supported algorithms +bench_algorithm!(cksum_sysv, "sysv"); +bench_algorithm!(cksum_bsd, "bsd"); +bench_algorithm!(cksum_crc, "crc"); +bench_algorithm!(cksum_crc32b, "crc32b"); +bench_algorithm!(cksum_md5, "md5"); +bench_algorithm!(cksum_sha1, "sha1"); +bench_algorithm!(cksum_sha2, "sha2", length); +bench_algorithm!(cksum_sha3, "sha3", length); +bench_algorithm!(cksum_blake2b, "blake2b"); +bench_algorithm!(cksum_sm3, "sm3"); +bench_algorithm!(cksum_sha224, "sha224"); +bench_algorithm!(cksum_sha256, "sha256"); +bench_algorithm!(cksum_sha384, "sha384"); +bench_algorithm!(cksum_sha512, "sha512"); +bench_algorithm!(cksum_blake3, "blake3"); +bench_shake_algorithm!(cksum_shake128, "shake128", Shake128); +bench_shake_algorithm!(cksum_shake256, "shake256", Shake256); + +/// Benchmark cksum with default CRC algorithm +#[divan::bench] +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()])); + }); +} + +/// Benchmark cksum with raw output format +#[divan::bench] +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()], + )); + }); +} + +/// Benchmark cksum processing multiple files +#[divan::bench] +fn cksum_multiple_files(bencher: Bencher) { + 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(), + ], + )); + }); +} + +fn main() { + divan::main(); +} From f8de10afcc591d17640b37dc18c4a3e51e5b5587 Mon Sep 17 00:00:00 2001 From: naoNao89 <90588855+naoNao89@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:27:21 +0700 Subject: [PATCH 2/4] fix: resolve unused import warnings in SHAKE benchmarks - Split bench_shake_algorithm macro into separate patterns for Shake128 and Shake256 - Only import the specific SHAKE type that is used in each macro invocation - Resolves CI compilation errors due to unused import warnings --- src/uu/cksum/benches/cksum_bench.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/uu/cksum/benches/cksum_bench.rs b/src/uu/cksum/benches/cksum_bench.rs index 9c38042a91c..ba17d5eb85f 100644 --- a/src/uu/cksum/benches/cksum_bench.rs +++ b/src/uu/cksum/benches/cksum_bench.rs @@ -49,15 +49,34 @@ macro_rules! bench_algorithm { // Since SHAKE algorithms have fundamental --length parameter conflicts in cksum, // we implement them using direct digest calculation for meaningful benchmarks macro_rules! bench_shake_algorithm { - ($algo_name:ident, $algo_str:expr, $shake_type:ty) => { + ($algo_name:ident, $algo_str:expr, Shake128) => { #[divan::bench] fn $algo_name(bencher: Bencher) { - use uucore::sum::{Digest, Shake128, Shake256}; + use uucore::sum::{Digest, Shake128}; let data = text_data::generate_by_size(100, 80); bencher.bench(|| { - let mut shake = <$shake_type>::new(); + let mut shake = Shake128::new(); + shake.hash_update(&data); + + // SHAKE algorithms can output any length, use 256 bits (32 bytes) for meaningful comparison + let mut output = [0u8; 32]; + shake.hash_finalize(&mut output); + + black_box(output); + }); + } + }; + ($algo_name:ident, $algo_str:expr, Shake256) => { + #[divan::bench] + fn $algo_name(bencher: Bencher) { + use uucore::sum::{Digest, Shake256}; + + let data = text_data::generate_by_size(100, 80); + + bencher.bench(|| { + let mut shake = Shake256::new(); shake.hash_update(&data); // SHAKE algorithms can output any length, use 256 bits (32 bytes) for meaningful comparison From caff1bc41407fb3dc99e837651f0e1d23916679e Mon Sep 17 00:00:00 2001 From: naoNao89 <90588855+naoNao89@users.noreply.github.com> Date: Wed, 29 Oct 2025 18:16:21 +0700 Subject: [PATCH 3/4] fix: parameterize SHA2/SHA3 benchmarks to use valid lengths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use length as parameter instead of hardcoded values - Add algorithm-specific lengths for each algorithm (224, 256, 384, 512 bits) - Resolves benchmarks running too fast (<500µs) due to invalid length parameters - All algorithms now produce meaningful hash outputs with proper timing --- src/uu/cksum/benches/cksum_bench.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/uu/cksum/benches/cksum_bench.rs b/src/uu/cksum/benches/cksum_bench.rs index ba17d5eb85f..d8350541d67 100644 --- a/src/uu/cksum/benches/cksum_bench.rs +++ b/src/uu/cksum/benches/cksum_bench.rs @@ -23,7 +23,7 @@ macro_rules! bench_algorithm { }); } }; - ($algo_name:ident, $algo_str:expr, length) => { + ($algo_name:ident, $algo_str:expr, $length:expr) => { #[divan::bench] fn $algo_name(bencher: Bencher) { let data = text_data::generate_by_size(100, 80); @@ -36,7 +36,7 @@ macro_rules! bench_algorithm { "--algorithm", $algo_str, "--length", - "1048576", + $length, file_path.to_str().unwrap(), ], )); @@ -96,14 +96,14 @@ bench_algorithm!(cksum_crc, "crc"); bench_algorithm!(cksum_crc32b, "crc32b"); bench_algorithm!(cksum_md5, "md5"); bench_algorithm!(cksum_sha1, "sha1"); -bench_algorithm!(cksum_sha2, "sha2", length); -bench_algorithm!(cksum_sha3, "sha3", length); +bench_algorithm!(cksum_sha2, "sha2", "256"); +bench_algorithm!(cksum_sha3, "sha3", "256"); bench_algorithm!(cksum_blake2b, "blake2b"); bench_algorithm!(cksum_sm3, "sm3"); -bench_algorithm!(cksum_sha224, "sha224"); -bench_algorithm!(cksum_sha256, "sha256"); -bench_algorithm!(cksum_sha384, "sha384"); -bench_algorithm!(cksum_sha512, "sha512"); +bench_algorithm!(cksum_sha224, "sha224", "224"); +bench_algorithm!(cksum_sha256, "sha256", "256"); +bench_algorithm!(cksum_sha384, "sha384", "384"); +bench_algorithm!(cksum_sha512, "sha512", "512"); bench_algorithm!(cksum_blake3, "blake3"); bench_shake_algorithm!(cksum_shake128, "shake128", Shake128); bench_shake_algorithm!(cksum_shake256, "shake256", Shake256); From 1350324f0e571c96240fde73668a7f40cd3055b4 Mon Sep 17 00:00:00 2001 From: naoNao89 <90588855+naoNao89@users.noreply.github.com> Date: Wed, 29 Oct 2025 20:59:32 +0700 Subject: [PATCH 4/4] fix: remove --length parameter from SHA224/256/384/512 benchmarks SHA224, SHA256, SHA384, and SHA512 algorithms don't support the --length parameter since the length is implicit in their algorithm names. Only the generic sha2 and sha3 algorithms require explicit length specification. --- src/uu/cksum/benches/cksum_bench.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/uu/cksum/benches/cksum_bench.rs b/src/uu/cksum/benches/cksum_bench.rs index d8350541d67..c316ec274a0 100644 --- a/src/uu/cksum/benches/cksum_bench.rs +++ b/src/uu/cksum/benches/cksum_bench.rs @@ -100,10 +100,10 @@ bench_algorithm!(cksum_sha2, "sha2", "256"); bench_algorithm!(cksum_sha3, "sha3", "256"); bench_algorithm!(cksum_blake2b, "blake2b"); bench_algorithm!(cksum_sm3, "sm3"); -bench_algorithm!(cksum_sha224, "sha224", "224"); -bench_algorithm!(cksum_sha256, "sha256", "256"); -bench_algorithm!(cksum_sha384, "sha384", "384"); -bench_algorithm!(cksum_sha512, "sha512", "512"); +bench_algorithm!(cksum_sha224, "sha224"); +bench_algorithm!(cksum_sha256, "sha256"); +bench_algorithm!(cksum_sha384, "sha384"); +bench_algorithm!(cksum_sha512, "sha512"); bench_algorithm!(cksum_blake3, "blake3"); bench_shake_algorithm!(cksum_shake128, "shake128", Shake128); bench_shake_algorithm!(cksum_shake256, "shake256", Shake256);