Docs for the Rust version; benchmarks; build.sh fixes
README, CLAUDE.md, man pages, the user guide and its screenshot script now describe the Rust build and the intentional behaviour changes, which docs/MIGRATION.md lists. Go and Rust micro-benchmarks for the same operations, and scripts/bench.sh for end-to-end comparison. build.sh exports its tree root to the per-target jobs and keeps logs out of the output directory; riscv64 musl builds use getrandom's raw syscall backend, since zig's musl getrandom never reaches the kernel there. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
//! The Rust side of scripts/bench.sh: the same operations as the Go
|
||||
//! oracle's Benchmark* functions, timed as the median of repeated runs.
|
||||
//! Run with `cargo bench --bench micro`.
|
||||
|
||||
use std::hint::black_box;
|
||||
use std::io::{Read, Write};
|
||||
use std::time::{Duration, Instant};
|
||||
use vault::crypto::{fury, kem, stream};
|
||||
|
||||
fn pattern(n: usize, salt: u8) -> Vec<u8> {
|
||||
(0..n).map(|i| (i.wrapping_mul(7) as u8) ^ salt).collect()
|
||||
}
|
||||
|
||||
/// Runs `f` until about two seconds have passed (at least 5 times) and
|
||||
/// prints the median and the spread.
|
||||
fn bench(name: &str, bytes: usize, mut f: impl FnMut()) {
|
||||
f(); // warm up
|
||||
let mut times = Vec::new();
|
||||
let start = Instant::now();
|
||||
while times.len() < 5 || (start.elapsed() < Duration::from_secs(2) && times.len() < 10_000) {
|
||||
let t = Instant::now();
|
||||
f();
|
||||
times.push(t.elapsed());
|
||||
}
|
||||
times.sort();
|
||||
let med = times[times.len() / 2];
|
||||
let (lo, hi) = (times[times.len() / 10], times[times.len() * 9 / 10]);
|
||||
let rate = if bytes > 0 {
|
||||
format!(" {:.0} MB/s", bytes as f64 / med.as_secs_f64() / 1e6)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
println!(
|
||||
"{name:<24} median {:>10.3} ms (p10 {:.3}, p90 {:.3}, n={}){rate}",
|
||||
med.as_secs_f64() * 1e3,
|
||||
lo.as_secs_f64() * 1e3,
|
||||
hi.as_secs_f64() * 1e3,
|
||||
times.len()
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let seed = pattern(32, 1);
|
||||
bench("derive", 0, || {
|
||||
black_box(kem::Identity::from_suite_seed(kem::SUITE_ID, &seed).unwrap());
|
||||
});
|
||||
let id = kem::Identity::from_suite_seed(kem::SUITE_ID, &seed).unwrap();
|
||||
let r = id.recipient();
|
||||
let fk: [u8; 32] = pattern(32, 2).try_into().unwrap();
|
||||
bench("wrap", 0, || {
|
||||
black_box(r.wrap(&fk, &mut vault::rng::os()));
|
||||
});
|
||||
let st = r.wrap(&fk, &mut vault::rng::os());
|
||||
bench("unwrap", 0, || {
|
||||
black_box(id.unwrap(std::slice::from_ref(&st)).unwrap());
|
||||
});
|
||||
let pt = pattern(4 << 20, 3);
|
||||
bench("object 4MiB", pt.len(), || {
|
||||
let mut ct = Vec::new();
|
||||
fury::encrypt_to(&mut ct, &r, &pt, &mut vault::rng::os());
|
||||
black_box(fury::decrypt_bounded(&ct[..], &id, pt.len()).unwrap());
|
||||
});
|
||||
let key = [0u8; 32];
|
||||
let big = vec![0u8; 64 << 20];
|
||||
bench("stream 64MiB", big.len(), || {
|
||||
let mut w = stream::StreamWriter::new(&key, Vec::with_capacity(big.len() + (1 << 16)));
|
||||
w.write_all(&big).unwrap();
|
||||
let ct = w.finish().unwrap();
|
||||
let mut out = Vec::with_capacity(big.len());
|
||||
stream::StreamReader::new(&key, &ct[..]).read_to_end(&mut out).unwrap();
|
||||
black_box(out);
|
||||
});
|
||||
let body = vault::keyfile::new_body(b"bench", b"", &mut vault::rng::os());
|
||||
bench("unlock", 0, || {
|
||||
black_box(vault::keyfile::unlock_body(&body, b"bench").unwrap());
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user