Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
matrix:
benchmark-target:
- { package: uu_base64 }
- { package: uu_cksum }
- { package: uu_cp }
- { package: uu_cut }
- { package: uu_du }
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/uu/cksum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
146 changes: 146 additions & 0 deletions src/uu/cksum/benches/cksum_bench.rs
Original file line number Diff line number Diff line change
@@ -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();
}
19 changes: 15 additions & 4 deletions src/uu/cksum/src/cksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use std::path::Path;
use uucore::checksum::{
ALGORITHM_OPTIONS_BLAKE2B, ALGORITHM_OPTIONS_BSD, ALGORITHM_OPTIONS_CRC,
ALGORITHM_OPTIONS_CRC32B, ALGORITHM_OPTIONS_SHA2, ALGORITHM_OPTIONS_SHA3,
ALGORITHM_OPTIONS_SYSV, ChecksumError, ChecksumOptions, ChecksumVerbose, HashAlgorithm,
LEGACY_ALGORITHMS, SUPPORTED_ALGORITHMS, calculate_blake2b_length, detect_algo, digest_reader,
perform_checksum_validation,
ALGORITHM_OPTIONS_SHAKE128, ALGORITHM_OPTIONS_SHAKE256, ALGORITHM_OPTIONS_SYSV, ChecksumError,
ChecksumOptions, ChecksumVerbose, HashAlgorithm, LEGACY_ALGORITHMS, SUPPORTED_ALGORITHMS,
calculate_blake2b_length, detect_algo, digest_reader, perform_checksum_validation,
};
use uucore::translate;

Expand Down Expand Up @@ -387,9 +387,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// Length for sha2 and sha3 should be saved, it will be validated
// afterwards if necessary.
(Some(len), ALGORITHM_OPTIONS_SHA2 | ALGORITHM_OPTIONS_SHA3) => Some(*len),
(None | Some(0), _) => None,
// Length for Blake2b if saved only if it's not zero.
(Some(len), ALGORITHM_OPTIONS_BLAKE2B) => calculate_blake2b_length(*len)?,
// Length for SHAKE algorithms is required and must be > 0
(Some(len), ALGORITHM_OPTIONS_SHAKE128 | ALGORITHM_OPTIONS_SHAKE256) => {
if *len == 0 {
return Err(ChecksumError::LengthRequiredForShake.into());
}
Some(*len)
}
// SHAKE algorithms require --length parameter
(None, ALGORITHM_OPTIONS_SHAKE128 | ALGORITHM_OPTIONS_SHAKE256) => {
return Err(ChecksumError::LengthRequiredForShake.into());
}
(None | Some(0), _) => None,
// a --length flag set with any other algorithm is an error.
_ => {
return Err(ChecksumError::LengthOnlyForBlake2bSha2Sha3.into());
Expand Down
2 changes: 2 additions & 0 deletions src/uucore/src/lib/features/checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ pub enum ChecksumError {
InvalidLengthFor(String),
#[error("--length is only supported with --algorithm blake2b, sha2, or sha3")]
LengthOnlyForBlake2bSha2Sha3,
#[error("--length is required for SHAKE algorithms")]
LengthRequiredForShake,
#[error("the --binary and --text options are meaningless when verifying checksums")]
BinaryTextConflict,
#[error("--text mode is only supported with --untagged")]
Expand Down