use std::fs;
use std::time::Instant;
use tempfile::tempdir;
use xzip::codec::EncodingKind;
use xzip::pack::pack_path;
use xzip::unpack::unpack_archive;
use xzip::verbosity::Verbosity;
const FILE_COUNT: usize = 6_000;
fn build_fixture_archive() -> (tempfile::TempDir, std::path::PathBuf) {
let temp = tempdir().expect("temp dir");
let input_dir = temp.path().join("input");
for i in 0..FILE_COUNT {
let sub = input_dir.join(format!("dir{i:04}"));
fs::create_dir_all(&sub).expect("create subdir");
let payload = format!("payload-{i:04}-{}", "x".repeat(64));
fs::write(sub.join("file.txt"), payload).expect("write file");
}
let archive = temp.path().join("large.zip");
pack_path(
&input_dir,
&archive,
EncodingKind::Utf8,
true,
&[],
&[],
Verbosity::default(),
)
.expect("pack fixture");
(temp, archive)
}
fn timed_unpack(
archive: &std::path::Path,
output: &std::path::Path,
jobs: usize,
label: &str,
) -> f64 {
if output.exists() {
fs::remove_dir_all(output).expect("clean output dir");
}
let started = Instant::now();
unpack_archive(
archive,
output,
EncodingKind::Utf8,
&[],
&[],
Verbosity::default(),
jobs,
)
.expect("unpack");
let elapsed = started.elapsed().as_secs_f64();
println!("{label}: {FILE_COUNT} files in {elapsed:.2}s");
elapsed
}
#[test]
#[ignore = "manual large-scale unpack benchmark"]
fn bench_large_unpack_sequential_vs_parallel() {
let (_temp, archive) = build_fixture_archive();
let base = _temp.path().join("out");
let sequential = timed_unpack(&archive, &base.join("sequential"), 1, "jobs=1");
let parallel = timed_unpack(&archive, &base.join("parallel"), 0, "jobs=0 (auto)");
let sample = fs::read(base.join("sequential/dir0000/file.txt")).expect("read sample");
assert!(sample.starts_with(b"payload-0000-"));
println!(
"speedup (jobs=0 / jobs=1): {:.2}x",
sequential / parallel.max(f64::EPSILON)
);
}
#[test]
#[ignore = "manual verbose large-scale unpack benchmark"]
fn bench_large_unpack_verbose() {
let (_temp, archive) = build_fixture_archive();
let output = _temp.path().join("out-verbose");
let started = Instant::now();
unpack_archive(
&archive,
&output,
EncodingKind::Utf8,
&[],
&[],
Verbosity(1),
1,
)
.expect("unpack");
let elapsed = started.elapsed().as_secs_f64();
println!("jobs=1 -v: {FILE_COUNT} files in {elapsed:.2}s");
}