-
Notifications
You must be signed in to change notification settings - Fork 123
Open
Description
zstd::stream::copy_decode
is 10-50x slower then zstd_safe::decompress
on my test input. And 2 zstd::stream::copy_decode
40% slower then zstd_safe::decompress
.
benchmark:
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn benchmark(c: &mut Criterion) {
let data = vec![
176, 234, 1, 2, 3, 4, 3, 2, 2, 1, 1, 4, 1, 0, 0, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 4, 1,
0, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 1, 0, 1, 4, 3, 4, 1, 0, 0, 0, 1, 2, 2,
1, 1, 4, 1, 1, 4, 1, 1, 4, 3, 4, 1, 0, 0, 0, 0, 1, 2, 0, 2, 1, 1, 4, 1, 0, 0, 0, 1, 4, 1,
0, 0, 0, 1, 4, 3, 4, 1, 1, 2, 2, 1, 0, 0, 1, 4, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 1, 4, 3, 4,
1, 0, 0, 1, 4, 1, 0, 0, 1, 4, 1, 0, 1, 4, 1, 1, 2, 0, 0, 0, 0, 2, 1, 1, 4, 1, 0, 0, 0, 0,
0, 1, 4, 1, 0, 1, 4, 1, 0, 0, 0, 1, 4, 3, 4, 1, 0, 0, 0, 0, 0, 1, 4, 1, 1, 2, 2, 3, 2, 2,
1, 0, 0, 1, 4, 3, 2, 0, 2, 3, 4, 1, 0, 0, 0, 0, 1, 2, 0, 2, 3, 4, 1, 0, 0, 1, 4, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 4, 1, 0, 1, 4, 1, 0, 0, 0, 0, 1, 4, 1, 0, 0, 1, 4, 1, 1, 4, 1, 0, 0,
0, 1, 4, 1, 1, 2, 2, 1, 0, 0, 0, 0, 1, 2, 2, 1, 1, 4, 3, 2, 2, 1, 0, 0, 0, 1, 4, 3, 4, 3,
2, 0, 2, 1, 0, 1, 4, 3, 4, 3, 4, 3, 4, 1, 0, 0, 0, 1, 4, 1, 0, 1, 4, 1, 0, 0, 0, 1, 2, 2,
1, 0, 0, 0, 1, 2, 2, 3, 2, 2, 1, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 1, 4, 1, 0, 0, 0, 1, 4, 1,
0, 1, 4, 3, 4, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 1, 4, 1, 0, 0, 0, 1, 4, 3, 4, 1, 1, 2, 2, 1,
0, 1, 4, 3, 4, 1, 0, 0, 1, 4, 1, 0, 0, 1, 4, 1, 1, 4, 3, 4, 3, 2, 2, 1, 0, 0, 0, 0, 1, 2,
2, 1, 1, 4, 1, 0, 0, 0, 1, 4, 1, 1, 4, 1, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
4, 1, 0, 0, 1, 2, 0, 2, 1, 0, 0, 1, 2, 0, 2, 3, 4, 1, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
0, 0, 0, 1, 4, 1, 0, 0, 1, 4, 1, 1, 4, 3, 4, 3, 4, 1, 1, 4, 1, 0, 0, 0, 0, 0, 0, 1, 4, 1,
0, 0,
];
let compressed_data = vec![
40, 181, 47, 253, 96, 225, 0, 45, 6, 0, 116, 3, 176, 234, 1, 2, 3, 4, 3, 2, 2, 1, 1, 4, 1,
0, 0, 0, 0, 1, 2, 2, 1, 0, 1, 4, 3, 1, 4, 3, 0, 3, 4, 1, 1, 2, 2, 0, 2, 0, 0, 4, 0, 3, 1,
3, 1, 1, 3, 0, 0, 0, 1, 4, 1, 0, 0, 62, 32, 32, 2, 131, 24, 195, 59, 108, 18, 105, 212,
128, 114, 129, 138, 11, 139, 55, 80, 2, 158, 238, 53, 218, 1, 142, 0, 149, 16, 0, 76, 113,
80, 46, 240, 237, 80, 48, 2, 171, 1, 8, 116, 235, 16, 109, 111, 88, 65, 160, 144, 1, 106,
249, 14, 70, 34, 117, 32, 239, 246, 223, 44, 33, 43, 208, 2, 127, 2, 218, 223, 144, 92,
192, 213, 1, 49, 0, 21, 228, 160, 132, 171, 183, 221, 153, 13, 7, 173, 12, 140, 50, 104,
13, 96, 33, 168, 26, 2, 16, 96, 195, 88, 36, 176, 14, 244, 6, 94, 22, 184, 1, 50, 128, 135,
3, 67, 18, 201, 228, 122, 18, 230, 167, 205, 194, 46, 111, 226, 45, 224, 11, 219, 192, 196,
8, 91, 51, 12,
];
let mut out = vec![];
zstd_safe_level(&mut out, &data, 3).unwrap();
// println!("zstd_safe_level: {:?}", out);
let mut dec = vec![];
zstd_safe_decompress(&mut dec, &out).unwrap();
assert_eq!(data, dec);
let mut dec2 = vec![];
decompress_zstd(&mut dec2, &out).unwrap();
assert_eq!(data, dec2);
for level in vec![-5, 2, 3, 4, 5] {
c.bench_function(format!("zstd {}", level).as_str(), |b| {
b.iter(|| black_box(compress2(&data, level, &mut out)));
});
c.bench_function(
format!("compress_zstd_safe_level {}", level).as_str(),
|b| {
b.iter(|| black_box(zstd_safe_level(&mut out, &data, level)));
},
);
}
c.bench_function("decompress_zstd", |b| {
b.iter(|| black_box(decompress_zstd(&mut dec, &compressed_data)));
});
c.bench_function("zstd_safe_decompress", |b| {
b.iter(|| black_box(zstd_safe_decompress(&mut dec2, &compressed_data)));
});
}
pub fn decompress_zstd(dst: &mut Vec<u8>, src: &[u8]) -> codecs::Result<()> {
zstd::stream::copy_decode(src, dst)?;
Ok(())
}
fn compress2(data: &[u8], level: i32, out: &mut Vec<u8>) {
zstd::stream::copy_encode(data, out, level).unwrap();
}
fn zstd_safe_decompress(dst: &mut Vec<u8>, src: &[u8]) -> anyhow::Result<()> {
let len = dst.len();
let cap = dst.capacity();
if cap > len {
match zstd_safe::decompress(dst, src) {
Ok(_) => {
return Ok(());
}
Err(_code) => {
//continue with resize
}
}
}
let cp = zstd_safe::decompress_bound(src)
.map_err(|e| anyhow::anyhow!(format!("zstd: {}", zstd_safe::get_error_name(e))))?
as usize;
dst.reserve(cp);
zstd_safe::decompress(dst, src)
.map_err(|e| anyhow::anyhow!(format!("zstd: {}", zstd_safe::get_error_name(e))))?;
Ok(())
}
fn zstd_safe_level(dst: &mut Vec<u8>, src: &[u8], level: i32) -> anyhow::Result<()> {
let len = dst.len();
let cap = dst.capacity();
if cap > len {
match zstd_safe::compress(dst, src, level) {
Ok(_) => {
return Ok(());
}
Err(_code) => {
//continue with resize
}
}
}
let cp = zstd_safe::compress_bound(src.len());
dst.reserve(cp);
zstd_safe::compress(dst, src, level)
.map_err(|e| anyhow::anyhow!(format!("zstd: {}", zstd_safe::get_error_name(e))))?;
Ok(())
}
criterion_group!(benches, benchmark);
criterion_main!(benches);
results:
zstd -5 time: [1.9967 µs 2.0104 µs 2.0246 µs]
compress_zstd_safe_level -5 time: [1.8046 µs 1.8093 µs 1.8142 µs]
zstd 2 time: [22.949 µs 23.126 µs 23.310 µs]
compress_zstd_safe_level 2. time: [2.2266 µs 2.2318 µs 2.2371 µs]
zstd 3 time: [49.526 µs 50.020 µs 50.530 µs]
compress_zstd_safe_level 3 time: [1.9953 µs 2.0016 µs 2.0079 µs]
zstd 4 time: [108.99 µs 110.95 µs 113.69 µs]
compress_zstd_safe_level 4 time: [3.7159 µs 4.3152 µs 5.0711 µs]
zstd 5 time: [145.64 µs 148.66 µs 152.30 µs]
compress_zstd_safe_level 5 time: [3.3225 µs 3.3312 µs 3.3411 µs]
decompress_zstd. time: [1.4370 µs 1.7105 µs 2.0412 µs]
zstd_safe_decompress time: [841.48 ns 1.0689 µs 1.3248 µs]
oronsh, thinkharderdev and ggbone1918
Metadata
Metadata
Assignees
Labels
No labels