mirror of
https://github.com/uutils/diffutils.git
synced 2026-06-10 15:48:59 -07:00
50057412bd
The utility should support all the arguments supported by GNU cmp and
perform slightly better.
On a "bad" scenario, ~36M files which are completely different, our
version runs in ~72% of the time of the original on my M1 Max:
> hyperfine --warmup 1 -i --output=pipe \
'cmp -l huge huge.3'
Benchmark 1: cmp -l huge huge.3
Time (mean ± σ): 3.237 s ± 0.014 s [User: 2.891 s, System: 0.341 s]
Range (min … max): 3.221 s … 3.271 s 10 runs
Warning: Ignoring non-zero exit code.
> hyperfine --warmup 1 -i --output=pipe \
'../target/release/diffutils cmp -l huge huge.3'
Benchmark 1: ../target/release/diffutils cmp -l huge huge.3
Time (mean ± σ): 2.392 s ± 0.009 s [User: 1.978 s, System: 0.406 s]
Range (min … max): 2.378 s … 2.406 s 10 runs
Warning: Ignoring non-zero exit code.
Our cmp runs in ~116% of the time when comparing libxul.so to the
chromium-browser binary with -l and -b. In a best case scenario of
comparing 2 files which are the same except for the last byte, our
tool is slightly faster.
52 lines
1.3 KiB
Rust
52 lines
1.3 KiB
Rust
#![no_main]
|
|
#[macro_use]
|
|
extern crate libfuzzer_sys;
|
|
use diffutilslib::cmp::{self, Cmp};
|
|
|
|
use std::ffi::OsString;
|
|
use std::fs::File;
|
|
use std::io::Write;
|
|
|
|
fn os(s: &str) -> OsString {
|
|
OsString::from(s)
|
|
}
|
|
|
|
fuzz_target!(|x: (Vec<u8>, Vec<u8>)| {
|
|
let args = vec!["cmp", "-l", "-b", "target/fuzz.cmp.a", "target/fuzz.cmp.b"]
|
|
.into_iter()
|
|
.map(|s| os(s))
|
|
.peekable();
|
|
|
|
let (from, to) = x;
|
|
|
|
File::create("target/fuzz.cmp.a")
|
|
.unwrap()
|
|
.write_all(&from)
|
|
.unwrap();
|
|
|
|
File::create("target/fuzz.cmp.b")
|
|
.unwrap()
|
|
.write_all(&to)
|
|
.unwrap();
|
|
|
|
let params =
|
|
cmp::parse_params(args).unwrap_or_else(|e| panic!("Failed to parse params: {}", e));
|
|
let ret = cmp::cmp(¶ms);
|
|
if from == to && !matches!(ret, Ok(Cmp::Equal)) {
|
|
panic!(
|
|
"target/fuzz.cmp.a and target/fuzz.cmp.b are equal, but cmp returned {:?}.",
|
|
ret
|
|
);
|
|
} else if from != to && !matches!(ret, Ok(Cmp::Different)) {
|
|
panic!(
|
|
"target/fuzz.cmp.a and target/fuzz.cmp.b are different, but cmp returned {:?}.",
|
|
ret
|
|
);
|
|
} else if ret.is_err() {
|
|
panic!(
|
|
"target/fuzz.cmp.a and target/fuzz.cmp.b caused cmp to error ({:?}).",
|
|
ret
|
|
);
|
|
}
|
|
});
|