use std::time::Instant;
use structured_zstd::encoding::{CompressionLevel, FrameCompressor};
use zstd::zstd_safe::zstd_sys;
fn repeated_log_lines(len: usize) -> Vec<u8> {
const LINES: &[&str] = &[
"ts=2026-03-26T21:39:28Z level=INFO msg=\"flush memtable\" tenant=demo table=orders region=eu-west\n",
"ts=2026-03-26T21:39:29Z level=INFO msg=\"rotate segment\" tenant=demo table=orders region=eu-west\n",
"ts=2026-03-26T21:39:30Z level=INFO msg=\"compact level\" tenant=demo table=orders region=eu-west\n",
"ts=2026-03-26T21:39:31Z level=INFO msg=\"write block\" tenant=demo table=orders region=eu-west\n",
];
let mut b = Vec::with_capacity(len);
while b.len() < len {
for l in LINES {
if b.len() == len {
break;
}
let r = len - b.len();
b.extend_from_slice(&l.as_bytes()[..l.len().min(r)]);
}
}
b
}
fn time_min<F: FnMut() -> usize>(iters: u32, mut f: F) -> (f64, usize) {
let mut best = f64::MAX;
let mut out = 0;
for _ in 0..iters {
let t = Instant::now();
out = f();
let us = t.elapsed().as_secs_f64() * 1e6;
if us < best {
best = us;
}
std::hint::black_box(out);
}
(best, out)
}
fn main() {
let dict = repeated_log_lines(8 * 1024);
let fixtures: &[(&str, usize)] = &[
("logs-512", 512),
("logs-1k", 1024),
("logs-4k", 4096),
("logs-16k", 16 * 1024),
];
let levels: &[i32] = &[-3, -1, 1, 2, 3, 6, 9, 12, 19];
let iters: u32 = 20000;
let dst_cap = unsafe { zstd_sys::ZSTD_compressBound(64 * 1024) };
println!(
"{:<9} {:>3} | {:>6} {:>7} | {:>6} {:>7} | rust:sz/sp",
"fixture", "lvl", "r_B", "r_us", "c_B", "c_us"
);
println!("{}", "-".repeat(60));
for (name, size) in fixtures {
let data = repeated_log_lines(*size);
for &level in levels {
let (r_us, r_b) = {
let mut cctx: FrameCompressor =
FrameCompressor::new(CompressionLevel::Level(level));
let dict_obj =
structured_zstd::decoding::Dictionary::from_raw_content(1, dict.clone())
.expect("raw dict");
cctx.set_dictionary_id_flag(false);
cctx.set_dictionary(dict_obj).expect("attach dict");
let mut out: Vec<u8> = Vec::new();
time_min(iters, || {
cctx.compress_independent_frame_into(&data, &mut out);
out.len()
})
};
let (c_us, c_b) = unsafe {
let cdict = zstd_sys::ZSTD_createCDict(dict.as_ptr().cast(), dict.len(), level);
let cctx = zstd_sys::ZSTD_createCCtx();
assert!(!cdict.is_null(), "ZSTD_createCDict returned null");
assert!(!cctx.is_null(), "ZSTD_createCCtx returned null");
let mut dst: Vec<u8> = vec![0u8; dst_cap];
let r = time_min(iters, || {
let rc = zstd_sys::ZSTD_compress_usingCDict(
cctx,
dst.as_mut_ptr().cast(),
dst_cap,
data.as_ptr().cast(),
data.len(),
cdict,
);
assert_eq!(zstd_sys::ZSTD_isError(rc), 0);
rc
});
zstd_sys::ZSTD_freeCCtx(cctx);
zstd_sys::ZSTD_freeCDict(cdict);
r
};
let sz = r_b as f64 / c_b as f64;
let sp = r_us / c_us;
println!(
"{name:<9} {level:>3} | {r_b:>6} {r_us:>7.2} | {c_b:>6} {c_us:>7.2} | {sz:.2}/{sp:.2}x"
);
}
println!();
}
}