137 lines
4.4 KiB
Rust
137 lines
4.4 KiB
Rust
// Compression benchmark: fast_inflate vs C libdeflater vs miniz_oxide
|
|
//
|
|
// Run with: cargo bench -p makepad-fast-inflate --bench compress_bench
|
|
|
|
use std::time::Instant;
|
|
|
|
fn make_test_data(size: usize) -> Vec<u8> {
|
|
let phrase = b"The quick brown fox jumps over the lazy dog. Makepad is fast! ";
|
|
let mut data = Vec::with_capacity(size);
|
|
while data.len() < size {
|
|
data.extend_from_slice(phrase);
|
|
}
|
|
data.truncate(size);
|
|
data
|
|
}
|
|
|
|
fn bench_compress(
|
|
label: &str,
|
|
data: &[u8],
|
|
level_rust: u32,
|
|
level_c: i32,
|
|
level_miniz: u8,
|
|
iterations: u32,
|
|
) {
|
|
let input_len = data.len();
|
|
|
|
// --- Rust fast_inflate ---
|
|
// Warm up
|
|
let _ = makepad_fast_inflate::zlib_compress(data, level_rust);
|
|
|
|
let start = Instant::now();
|
|
let mut rust_compressed_len = 0;
|
|
for _ in 0..iterations {
|
|
let out = makepad_fast_inflate::zlib_compress(data, level_rust);
|
|
rust_compressed_len = out.len();
|
|
}
|
|
let rust_elapsed = start.elapsed();
|
|
let rust_ns = rust_elapsed.as_nanos() as f64 / iterations as f64;
|
|
let rust_throughput = input_len as f64 / (rust_ns / 1e9) / 1e6;
|
|
|
|
// --- C libdeflater ---
|
|
let start = Instant::now();
|
|
let mut c_compressed_len = 0;
|
|
for _ in 0..iterations {
|
|
let mut comp =
|
|
libdeflater::Compressor::new(libdeflater::CompressionLvl::new(level_c).unwrap());
|
|
let bound = comp.zlib_compress_bound(input_len);
|
|
let mut out = vec![0u8; bound];
|
|
c_compressed_len = comp.zlib_compress(data, &mut out).unwrap();
|
|
}
|
|
let c_elapsed = start.elapsed();
|
|
let c_ns = c_elapsed.as_nanos() as f64 / iterations as f64;
|
|
let c_throughput = input_len as f64 / (c_ns / 1e9) / 1e6;
|
|
|
|
// --- miniz_oxide ---
|
|
let start = Instant::now();
|
|
let mut miniz_compressed_len = 0;
|
|
for _ in 0..iterations {
|
|
let out = miniz_oxide::deflate::compress_to_vec_zlib(data, level_miniz);
|
|
miniz_compressed_len = out.len();
|
|
}
|
|
let miniz_elapsed = start.elapsed();
|
|
let miniz_ns = miniz_elapsed.as_nanos() as f64 / iterations as f64;
|
|
let miniz_throughput = input_len as f64 / (miniz_ns / 1e9) / 1e6;
|
|
|
|
let ratio_vs_c = rust_ns / c_ns;
|
|
let ratio_vs_miniz = miniz_ns / rust_ns;
|
|
|
|
println!(
|
|
"{:>20} Rust: {:>7.1} MB/s ({:>5}b) C: {:>7.1} MB/s ({:>5}b) miniz: {:>7.1} MB/s ({:>5}b) Rust/C: {:.2}x miniz/Rust: {:.2}x",
|
|
label,
|
|
rust_throughput, rust_compressed_len,
|
|
c_throughput, c_compressed_len,
|
|
miniz_throughput, miniz_compressed_len,
|
|
ratio_vs_c, ratio_vs_miniz,
|
|
);
|
|
}
|
|
|
|
fn main() {
|
|
println!("Compression benchmark: fast_inflate vs C libdeflater vs miniz_oxide");
|
|
println!("{}", "=".repeat(140));
|
|
|
|
let sizes = [
|
|
("1 KB", 1_000),
|
|
("10 KB", 10_000),
|
|
("100 KB", 100_000),
|
|
("1 MB", 1_000_000),
|
|
];
|
|
|
|
// Level 1 (fastest)
|
|
println!("\nLevel 1 (fastest):");
|
|
println!("{}", "-".repeat(140));
|
|
for &(label, size) in &sizes {
|
|
let data = make_test_data(size);
|
|
let iterations = (5_000_000 / size).max(5) as u32;
|
|
bench_compress(label, &data, 1, 1, 1, iterations);
|
|
}
|
|
|
|
// Level 6 (default)
|
|
println!("\nLevel 6 (default):");
|
|
println!("{}", "-".repeat(140));
|
|
for &(label, size) in &sizes {
|
|
let data = make_test_data(size);
|
|
let iterations = (2_000_000 / size).max(5) as u32;
|
|
bench_compress(label, &data, 6, 6, 6, iterations);
|
|
}
|
|
|
|
// Level 9 (best)
|
|
println!("\nLevel 9 (best):");
|
|
println!("{}", "-".repeat(140));
|
|
for &(label, size) in &sizes {
|
|
let data = make_test_data(size);
|
|
let iterations = (1_000_000 / size).max(5) as u32;
|
|
bench_compress(label, &data, 9, 9, 9, iterations);
|
|
}
|
|
|
|
// Low compressibility (random) data
|
|
println!("\nRandom data (low compressibility), level 6:");
|
|
println!("{}", "-".repeat(140));
|
|
use rand::Rng;
|
|
let mut rng = rand::thread_rng();
|
|
for &(label, size) in &[
|
|
("rand 10 KB", 10_000),
|
|
("rand 100 KB", 100_000),
|
|
("rand 1 MB", 1_000_000),
|
|
] {
|
|
let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
|
|
let iterations = (2_000_000 / size).max(5) as u32;
|
|
bench_compress(label, &data, 6, 6, 6, iterations);
|
|
}
|
|
|
|
println!();
|
|
println!(
|
|
"Rust/C < 1.0 means Rust is faster. miniz/Rust > 1.0 means Rust is faster than miniz."
|
|
);
|
|
println!("Compressed sizes shown in parentheses (lower = better ratio).");
|
|
}
|