diff --git a/Cargo.toml b/Cargo.toml index c3e0494..58be340 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ sha2 = "0.10.0" reed-solomon-16 = "0.1.0" reed-solomon-erasure = { version = "6.0.0", features = [ "simd-accel" ] } reed-solomon-novelpoly = "2.0.0" +leopard-codec = "0.1.0" [lib] bench = false diff --git a/README.md b/README.md index ad374d7..2dddb8f 100644 --- a/README.md +++ b/README.md @@ -170,8 +170,7 @@ using chosen [`Engine`] and [`Rate`]. ## Benchmarks against other crates Use `cargo run --release --example quick-comparison` -to run few simple benchmarks against [`reed-solomon-16`], [`reed-solomon-erasure`] -and [`reed-solomon-novelpoly`] crates. +to run few simple benchmarks against [`reed-solomon-16`], [`reed-solomon-erasure`], [`reed-solomon-novelpoly`] and [`leopard-codec`] crates. This crate is the fastest in all cases on my AMD Ryzen 5 3600, except in the case of decoding with about 42 or fewer recovery shards. @@ -181,6 +180,7 @@ which can dominate at really small data amounts. [`reed-solomon-16`]: https://crates.io/crates/reed-solomon-16 [`reed-solomon-erasure`]: https://crates.io/crates/reed-solomon-erasure [`reed-solomon-novelpoly`]: https://crates.io/crates/reed-solomon-novelpoly +[`leopard-codec`]: https://crates.io/crates/leopard-codec ## Running tests diff --git a/examples/quick-comparison.rs b/examples/quick-comparison.rs index 1601527..cb83411 100644 --- a/examples/quick-comparison.rs +++ b/examples/quick-comparison.rs @@ -23,13 +23,14 @@ fn main() { println!(" µs (init) µs (encode) µs (decode)"); println!(" --------- ----------- -----------"); - for count in [32, 64, 128, 256, 512, 1024, 4 * 1024, 32 * 1024] { + for count in [8, 16, 32, 64, 128, 256, 512, 1024, 4 * 1024, 32 * 1024] { println!("\n{}:{} ({} kiB)", count, count, SHARD_BYTES / 1024); test_reed_solomon_simd(count); test_reed_solomon_16(count); test_reed_solomon_novelpoly(count); if count <= 128 { test_reed_solomon_erasure_8(count); + test_leopard_codec(count); } if count <= 512 { test_reed_solomon_erasure_16(count); @@ -284,3 +285,53 @@ fn test_reed_solomon_novelpoly(count: usize) { assert_eq!(reconstructed, original); } + +// ====================================================================== +// leopard-codec + +fn test_leopard_codec(count: usize) { + // INIT + + // I don't see a way to ask the library to initialize the tables. + // Also the `leopard_codec::lut` module is private, so we can't do it directly. + + print!("> leopard-codec ?"); + + // CREATE ORIGINAL + + let mut original = vec![vec![0u8; SHARD_BYTES]; count]; + let mut rng = ChaCha8Rng::from_seed([0; 32]); + for shard in &mut original { + rng.fill::<[u8]>(shard); + } + + let mut recovery = vec![vec![0u8; SHARD_BYTES]; count]; + + let mut all_shards: Vec<&mut Vec> = + original.iter_mut().chain(recovery.iter_mut()).collect(); + + // ENCODE + + let start = Instant::now(); + leopard_codec::encode(&mut all_shards, count).unwrap(); + + let elapsed = start.elapsed(); + print!("{:14}", elapsed.as_micros()); + + // PREPARE DECODE + + let mut restored = vec![Vec::::new(); count]; + let mut restored_and_recovery: Vec<&mut Vec> = + restored.iter_mut().chain(recovery.iter_mut()).collect(); + + // DECODE + + let start = Instant::now(); + leopard_codec::reconstruct(&mut restored_and_recovery, count).unwrap(); + + let elapsed = start.elapsed(); + println!("{:14}", elapsed.as_micros()); + + // CHECK + assert_eq!(restored, original); +}