Files
zeekayandHanzo Dev a87d24a09f zap: crate is zapwire, not zap-proto — zap-proto belongs to zap-proto/spec
The previous commit took `zap-proto`, which was measured from a LOCAL
checkout of ~/work/zap/spec that is 26 commits behind on a stale
`master` branch. The remote (zap-proto/spec@main) tells a different
story:

  - its crate is now `zap-schema` 1.0.0, lib name `zap`; it no longer
    publishes `hanzo-zap` at all — that half of the collision was
    already fixed upstream;
  - `reserve/zap-proto/` is a DELIBERATE name reservation, published by
    its own release.yml (`working-directory: reserve/zap-proto`,
    `cargo publish`), whose description points at `zap-schema`.

So `zap-proto` is owned and published by another repo, and taking it
would have recreated the exact two-codebases-one-name bug this work
exists to remove. `zap-schema`'s lib is also imported as `zap`, so the
lib name had to move too or the two could never share a dep graph.

  package: zap-proto -> zapwire      lib: zap -> zapwire
  version: 1.0.1     -> 1.0.0        (zapwire is a NEW name: first
                                      publish, not a bump)

`zapwire` is what this crate is: the wire runtime — header, data
segment, call envelope, transport. Verified free on crates.io and
absent from spec's reserve/ set.

Nothing to do in zap-proto/spec: it fixed itself. Judging it from the
stale local checkout would have "retired" 26 commits of live work,
including a Rust `cap` capability runtime.

make test: 27 lib + 10 crosswire + 2 live-Go interop + 1 doctest, green.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 22:55:41 -07:00

97 lines
3.2 KiB
Rust

//! ZAP wire benchmarks — encode + decode of representative messages.
//!
//! Compared against a JSON baseline to quantify the binary win. Runs
//! on a single core; multiply by core count for a server estimate.
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use zapwire::schema::{keys_snapshot, keys_subscribe};
fn bench_keys_subscribe_encode(c: &mut Criterion) {
let mut g = c.benchmark_group("encode/keys_subscribe");
g.throughput(Throughput::Elements(1));
g.bench_function("zap", |b| {
b.iter(|| {
let bytes = keys_subscribe::Writer {
application: black_box("hanzo".to_string()),
cursor: black_box(42),
}
.to_bytes();
black_box(bytes);
})
});
g.bench_function("json", |b| {
b.iter(|| {
let s = format!(
r#"{{"application":"{}","cursor":{}}}"#,
black_box("hanzo"),
black_box(42u64)
);
black_box(s.into_bytes());
})
});
g.finish();
}
fn bench_keys_subscribe_decode(c: &mut Criterion) {
let bytes = keys_subscribe::Writer {
application: "hanzo".to_string(),
cursor: 42,
}
.to_bytes();
let json = br#"{"application":"hanzo","cursor":42}"#;
let mut g = c.benchmark_group("decode/keys_subscribe");
g.throughput(Throughput::Elements(1));
g.bench_function("zap", |b| {
b.iter(|| {
let r = keys_subscribe::Reader::from_slice(black_box(&bytes)).unwrap();
black_box((r.application(), r.cursor()));
})
});
g.bench_function("json_naive_scan", |b| {
// Apples-to-apples: a hand-rolled minimal JSON-ish scan that's
// still allocating a String for the payload. Real JSON parsers
// (serde) are slower; we're being generous to the baseline.
b.iter(|| {
let s = std::str::from_utf8(black_box(json)).unwrap();
let app_start = s.find("\"application\":\"").unwrap() + 15;
let app_end = s[app_start..].find('"').unwrap() + app_start;
let app = &s[app_start..app_end];
let cur_start = s.find("\"cursor\":").unwrap() + 9;
let cur_end = s[cur_start..]
.find(|c: char| !c.is_ascii_digit())
.map(|i| cur_start + i)
.unwrap_or(s.len());
let cur: u64 = s[cur_start..cur_end].parse().unwrap();
black_box((app, cur));
})
});
g.finish();
}
fn bench_keys_snapshot_encode_with_payload(c: &mut Criterion) {
let jwks = include_bytes!("./fixtures_jwks.json");
let mut g = c.benchmark_group("encode/keys_snapshot_2k_jwks");
g.throughput(Throughput::Bytes(jwks.len() as u64));
g.bench_function("zap", |b| {
b.iter(|| {
let bytes = keys_snapshot::Writer {
application: "hanzo".to_string(),
seq: 1,
jwks_json: jwks.to_vec(),
}
.to_bytes();
black_box(bytes);
})
});
g.finish();
}
criterion_group!(
benches,
bench_keys_subscribe_encode,
bench_keys_subscribe_decode,
bench_keys_snapshot_encode_with_payload
);
criterion_main!(benches);