perf: major encode/decode optimization via const copy_from_slice and batch zero fill
Encode: rewrite to two-pass (scan + copy_from_slice) leveraging Rust 1.93's const fn copy_from_slice for memcpy at runtime while keeping const fn encode. Sub-slice scan pattern helps LLVM eliminate bounds checks. Added zero byte fast path for all-zeros workloads. Now leads corncobs on nonzero/mixed encode. Decode: batch consecutive 0x01 codes (all-zeros data) and fill zeros via memset instead of per-byte loop. Decode zeros throughput jumps from ~1.2 GB/s to ~4.6 GB/s, now 3x faster than corncobs on that workload. Bump MSRV 1.83 → 1.93 for const copy_from_slice. Update dev-deps: cobs 0.3→0.5, criterion 0.5→0.8, rand 0.8→0.10. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
4 files changed
+73
-27
No files matched your search
+8
-4
@@ -1,4 +1,6 @@
|
||||
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
||||
use std::hint::black_box;
|
||||
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
|
||||
|
||||
// ── Test payloads ───────────────────────────────────────────────────
|
||||
|
||||
@@ -51,9 +53,11 @@ fn cobs_encode(data: &[u8]) -> Vec<u8> {
|
||||
}
|
||||
|
||||
fn cobs_decode(encoded: &[u8], out: &mut [u8]) -> usize {
|
||||
// unwrap_or(0): the cobs crate returns Err(EmptyFrame) for empty input,
|
||||
// which is valid COBS. We treat it as 0 decoded bytes for benchmarking.
|
||||
cobs::decode(encoded, out).unwrap_or(0)
|
||||
// The cobs crate returns DecodeReport on success or Err(EmptyFrame)
|
||||
// for empty input. We extract parsed_size, treating errors as 0.
|
||||
cobs::decode(encoded, out)
|
||||
.map(|report| report.parsed_size())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
// ── Benchmarks ──────────────────────────────────────────────────────
|
||||
|
||||
Reference in new issue
Block a user