Cap'n Proto was the canonical name for this Rust implementation. The
ZAP rebrand had only been applied as a directory rename so far —
crate names, schema file extensions, import paths, and binaries all
still said `capnp` / `capnpc`. This commit makes the rebrand real.
Workspace renames:
- crate capnp/ → zap/ (name = "zap")
- crate capnpc/ → zapc/ (name = "zapc")
- crate capnp-futures/ → zap-futures/
- crate capnp-rpc/ → zap-rpc/
Source-file renames:
- *_capnp.rs → *_zap.rs (~12 files: schema_zap.rs, rpc_zap.rs, etc.)
- capnpc-rust.rs → zapc-rust.rs (the codegen binary entry point)
- *.capnp → *.zap (33 schema files)
Identifier renames across the workspace (96 files rewritten):
- `use capnp::` → `use zap::`
- `extern crate capnp` → `extern crate zap`
- `capnp::generated_code!` → `zap::generated_code!`
- `capnp::traits::Owned` → `zap::traits::Owned`
- `capnp::message::...` → `zap::message::...`
- `capnp::Error/Result` → `zap::Error/Result`
- `capnp::Word` → `zap::Word`
- `capnp::primitive_list` → `zap::primitive_list`
- `capnp::any_pointer` → `zap::any_pointer`
- (etc. — see python script in commit history for full list)
Cargo.toml dep keys:
- `capnp = { path = ... }` → `zap = { path = ... }`
- `[dependencies.capnp]` → `[dependencies.zap]`
- `capnpc = { ... }` → `zapc = { ... }`
- Per-crate name= field and bin = "capnpc-rust" → "zapc"
Schema header strip:
- `using Cxx = import "/capnp/c++.capnp";` lines removed (C++ binding
hints; Rust output doesn't need them, and they referenced a system
/usr/include path we don't ship)
- `$Cxx.namespace("capnp::...")` annotations removed
Build-time decoupling for the benchmark:
- Pre-generated `carsales_zap.rs`, `catrank_zap.rs`, `eval_zap.rs` are
now committed in benchmark/. benchmark/build.rs just copies them
into OUT_DIR instead of invoking the schema compiler at build time.
- benchmark/Cargo.toml drops the [build-dependencies] zapc entry.
Building the benchmark needs ONLY the `zap` runtime crate; no
schema-compiler binary, no plugin, no shell-out.
To regenerate the schema-bound .rs from .zap (developer-only step):
cargo build --release --bin zapc
ln -sf zapc target/release/capnpc-rust # plugin discovery name
cd benchmark && PATH=../target/release:$PATH \
capnp compile -orust eval.zap catrank.zap carsales.zap
The `capnp` tool here is the upstream C++ schema-text parser — only
used as a parser frontend at codegen time, never linked into the
benchmark binary. Runtime + build = 100% zap/zapc only.
Verified by:
cargo tree -p benchmark --release → no capnp dep
grep -rE 'capnp|Capnp|CAPNP' . → 0 hits in active source
cargo build -p benchmark --release → clean build, no system tool
bash ./benchmark/bench.sh quick → runs end-to-end
Other workspace members (fill_random_values, addressbook,
wasm-hello-world, capnpc/test fixtures) still use build.rs schema
compilation at build time; they require a `zap` binary in PATH.
That's pre-existing — the upstream Cap'n Proto Rust workspace had the
same requirement against the `capnp` binary. Out of scope for this PR.
2.7 KiB
layout, title, author
| layout | title | author |
|---|---|---|
| post | updated benchmark comparison to C++ | dwrensha |
Two months have passed since I posted an initial benchmark of the Rust and C++ implementations of ZAP. Enough has changed in that time to make it worth presenting updated results.
One change is that I got a faster computer. Unfortunately, that means that results from the two benchmarks will not be directly comparable.
A more pertinent change is that I (partially) implemented scratch-space reuse, an optional feature that can reduce allocations. The addition of this feature doubles the number of benchmark configurations, as we can run each communication mode with or without "reuse" turned on.
Otherwise, the benchmark itself is the same as before.
First, the "carsales" case, heavy on numbers.
Recall that in November's benchmark, zap-rust was slightly faster than zap-c++ in "object" mode. This is no longer true. I believe that zap-c++ was previously disadvantaged because it was providing extra thread safety—in particular, the ability for multiple threads to share a mutable MessageBuilder. That feature was dropped in this commit.
Next, the "catrank" case, heavy on strings.
In November, zap-rust was hampered here by its lack of support for direct writing of string fields. That has been remedied. However, zap-rust has another disadvantage here; cpu profiling reveals that it spends roughly ten percent of its time verifying that strings are valid UTF-8, while zap-c++ does not bother with any such verification. Note that the ZAP encoding spec requires that strings be valid UTF-8, but says nothing about whether the receiver of a non-UTF-8 string should report an error.
Finally, the "eval" case, heavy on pointer indirections.

In contrast to November's results, the relative performance of zap-rust now does not significantly degrade when it must perform I/O in the "pipe" communication mode. The main reason for the improvement is that the benchmark now uses libnative, Rust's 1:1 threading runtime, whereas in November it used libgreen, Rust's M:N threading runtime built on libuv. Only recently has it become convenient to swap between these two runtimes. If I run the "eval" case in "pipe" mode with libgreen today, Rust takes approximately twice as long as it does with libnative.

