Skip to content

Instantly share code, notes, and snippets.

@alexcrichton
Created October 19, 2016 17:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexcrichton/e0f6c59113c79d5a2505ea54c62bd3f5 to your computer and use it in GitHub Desktop.
Save alexcrichton/e0f6c59113c79d5a2505ea54c62bd3f5 to your computer and use it in GitHub Desktop.
extern crate zstd;
extern crate flate2;
extern crate xz2;
extern crate brotli2;
use std::collections::BTreeMap;
use std::env;
use std::time::Duration;
use std::fs::File;
use std::io::Read;
use std::time::Instant;
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}", stringify!($e), e),
})
}
fn main() {
let cwd = env::current_dir().unwrap();
let mut algos = BTreeMap::new();
for e in t!(cwd.read_dir()).map(|e| t!(e)) {
if e.path().extension().and_then(|s| s.to_str()) != Some("rlib") {
continue
}
let p = t!(e.path().read_dir())
.map(|e| t!(e))
.map(|e| e.path())
.find(|p| p.extension().and_then(|s| s.to_str()) == Some("deflate"))
.unwrap();
let mut compressed_contents = Vec::new();
t!(t!(File::open(&p)).read_to_end(&mut compressed_contents));
let mut contents = Vec::new();
t!(flate2::read::DeflateDecoder::new(&compressed_contents[23..])
.read_to_end(&mut contents));
println!("=========================================================");
println!("path: {:?}", e.path().file_name());
println!("size: {:?}", contents.len());
for i in 0..10 {
let name = format!("xz{}", i);
doit(&name, &mut algos, &contents, &mut |contents| {
let mut xz = Vec::new();
t!(xz2::read::XzEncoder::new(&contents[..], i).read_to_end(&mut xz));
xz
});
}
doit("flate fast", &mut algos, &contents, &mut |contents| {
let mut flate = Vec::new();
t!(flate2::read::DeflateEncoder::new(&contents[..],
flate2::Compression::Fast).read_to_end(&mut flate));
flate
});
doit("flate default", &mut algos, &contents, &mut |contents| {
let mut flate = Vec::new();
t!(flate2::read::DeflateEncoder::new(&contents[..],
flate2::Compression::Default).read_to_end(&mut flate));
flate
});
doit("flate best", &mut algos, &contents, &mut |contents| {
let mut flate = Vec::new();
t!(flate2::read::DeflateEncoder::new(&contents[..],
flate2::Compression::Best).read_to_end(&mut flate));
flate
});
for i in 0..10 {
let name = format!("brotli{}", i);
doit(&name, &mut algos, &contents, &mut |contents| {
let mut brotli = Vec::new();
t!(brotli2::read::BrotliEncoder::new(&contents[..], 6).read_to_end(&mut brotli));
brotli
});
}
for i in 0..10 {
let name = format!("zstd{}", i);
doit(&name, &mut algos, &contents, &mut |contents| {
zstd::stream::encode_all(&contents[..], i).unwrap()
});
}
}
println!("============================================================");
for (k, v) in algos {
let millis = v.time.as_secs() as u32 * 1_000;
let nanos = v.time.subsec_nanos();
let millis = millis + nanos / 1_000_000;
println!("{:<18} {:8} (-{:02.2}%) {:3}.{:03}ms",
k,
v.total_compressed,
100.0 - 100.0 * (v.total_compressed as f64 / (v.total_uncompressed as f64)),
millis,
(nanos % 1_000_000) / 1_000);
}
}
struct Algorithm {
total_uncompressed: usize,
total_compressed: usize,
time: Duration,
}
fn doit(name: &str,
algos: &mut BTreeMap<String, Algorithm>,
data: &[u8],
f: &mut FnMut(&[u8]) -> Vec<u8>) {
let start = Instant::now();
let small = f(data);
let end = start.elapsed();
let algo = algos.entry(name.to_string()).or_insert(Algorithm {
total_uncompressed: 0,
total_compressed: 0,
time: Duration::new(0, 0),
});
algo.total_uncompressed += data.len();
algo.total_compressed += small.len();
algo.time += end;
let millis = end.as_secs() as u32 * 1_000;
let nanos = end.subsec_nanos();
let millis = millis + nanos / 1_000_000;
println!("{:<18} {:8} (-{:02.2}%) {:3}.{:03}ms",
name,
small.len(),
100.0 - 100.0 * (small.len() as f64 / (data.len() as f64)),
millis,
(nanos % 1_000_000) / 1_000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment