feat: add benchmarks, justfile, optimize throughput, harden quality gates
Benchmarking & comparison: - Add criterion benchmarks (ucobs vs cobs 0.3 vs corncobs 0.1) - Add Python cobs benchmark script - Add performance comparison section to README with full results Performance: - Rewrite encode to scan-and-bulk-copy via copy_from_slice - Rewrite decode to bulk-copy via copy_from_slice - ~2-4x throughput improvement; now matches corncobs on most workloads Quality hardening: - Add #![forbid(unsafe_code)], #![warn(missing_docs)], #[must_use] - Add [lints.rust] unsafe_code = "forbid" in Cargo.toml - Add rust-version (MSRV) = "1.56" - Add docs.rs metadata - 106 tests: 80 unit/corpus + 25 property tests (25k cases each = 625k total) - External test vectors from: Wikipedia, Cheshire & Baker paper, nanocobs, cobs-c, cobs2-rs, Jacques Fortier, Python cobs package - Add fuzz_small_dest fuzz target (encode/decode with undersized buffers) - Improve doc examples to show sentinel append/strip convention Infrastructure: - Add justfile with test (nextest), check, bench, fuzz, miri, fmt targets - cargo-nextest for parallel test execution - Update .gitignore for Python cache files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
10 files changed
+1187
-99
No files matched your search
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Benchmark Python cobs encode/decode vs ucobs (reference timing only).
|
||||
|
||||
Requires: pip install cobs
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
|
||||
def payload_zeros(n: int) -> bytes:
|
||||
return b"\x00" * n
|
||||
|
||||
|
||||
def payload_nonzero(n: int) -> bytes:
|
||||
return bytes((i % 255 + 1) for i in range(n))
|
||||
|
||||
|
||||
def payload_mixed(n: int) -> bytes:
|
||||
return bytes(i % 256 for i in range(n))
|
||||
|
||||
|
||||
def bench(func, data, iterations=10_000):
|
||||
start = time.perf_counter()
|
||||
for _ in range(iterations):
|
||||
func(data)
|
||||
elapsed = time.perf_counter() - start
|
||||
return elapsed
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
from cobs import cobs as cobs_mod
|
||||
except ImportError:
|
||||
print("ERROR: python cobs package not installed. Run: pip install cobs")
|
||||
return
|
||||
|
||||
sizes = [0, 1, 10, 64, 254, 255, 256, 1024, 4096]
|
||||
payloads = [
|
||||
("zeros", payload_zeros),
|
||||
("nonzero", payload_nonzero),
|
||||
("mixed", payload_mixed),
|
||||
]
|
||||
iterations = 10_000
|
||||
|
||||
print(f"{'operation':<30} {'size':>6} {'iters':>7} {'total_ms':>10} {'per_op_us':>10} {'MB/s':>10}")
|
||||
print("-" * 80)
|
||||
|
||||
for name, make in payloads:
|
||||
for size in sizes:
|
||||
data = make(size)
|
||||
|
||||
# Encode
|
||||
elapsed = bench(cobs_mod.encode, data, iterations)
|
||||
per_op_us = (elapsed / iterations) * 1_000_000
|
||||
mbps = (size * iterations / elapsed / 1_000_000) if elapsed > 0 and size > 0 else 0
|
||||
print(f"{'python-cobs encode/' + name:<30} {size:>6} {iterations:>7} {elapsed*1000:>10.2f} {per_op_us:>10.3f} {mbps:>10.1f}")
|
||||
|
||||
# Decode
|
||||
encoded = cobs_mod.encode(data)
|
||||
elapsed = bench(cobs_mod.decode, encoded, iterations)
|
||||
per_op_us = (elapsed / iterations) * 1_000_000
|
||||
mbps = (size * iterations / elapsed / 1_000_000) if elapsed > 0 and size > 0 else 0
|
||||
print(f"{'python-cobs decode/' + name:<30} {size:>6} {iterations:>7} {elapsed*1000:>10.2f} {per_op_us:>10.3f} {mbps:>10.1f}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user