Benchmarks
What ruststream-pulsar costs on every message: throughput against the raw pulsar client, and
instructions and allocations of its code.
Against a raw client
The first chart runs one scenario three ways on a real Pulsar broker. Raw client drives a
consumer of the pulsar crate directly. Broker crate drives this crate's subscription with a loop
of its own and no runtime. RustStream is the service a user writes, a #[subscriber] handler in
an app. The first gap is what this crate costs over the client it wraps, and the second is what the
runtime adds on top.
Each loop is a bar from its best round to its slowest, with a dot at the best round and a notch at the median. The zero of the axis is the raw client's best round, and a dot right of zero is slower. A hollow dot is a loop whose difference from the raw client is smaller than the spread of the rounds. The table under the chart prints the best round with the median in parentheses.
The two scenarios differ in the subscription type. The server keeps a
redelivery count for every message of a Shared subscription and none for an Exclusive one. Both
run one consumer, so what separates them is that bookkeeping, not the cost of sharing.
Cost of the code
The second chart counts what one message costs on the service's thread: instructions under
callgrind and allocations under DHAT, in the steady state. Each scenario is a service on
PulsarBroker against the same broker, with a Shared
subscription over a persistent topic. The count includes the framework's dispatch, this crate's code
and the work of the pulsar client, whose connection and consumer run on the service's runtime. The
broker is another process and is not counted. Cold start is what connecting, subscribing and
taking the first message cost once.
Results
- Raw client
- Broker crate
- RustStream
- rounds, best to slowest
- best round
- median round
- spread of the rounds
- indistinguishable
ruststream-pulsar 0.7.0 on ruststream 0.7.0, AMD Ryzen 9 7900X 12-Core Processor, Linux 7.2.11-x64v3-xanmod1-1, apachepulsar/pulsar:4.1.2 in Docker on localhost, measured 2026-10-18. How the numbers were taken
- indistinguishable
- indistinguishable (broker-bound)
- indistinguishable
- indistinguishable (broker-bound)
Show the numbers as a table
| Scenario | Raw client | Broker crate | RustStream | Overhead |
|---|---|---|---|---|
| Exclusive subscription, 128 B JSON, ack each | 27,594 msg/s (27,518) | 27,656 msg/s (27,554) (indistinguishable over the client) | 27,652 msg/s (27,586) | indistinguishable (broker-bound) |
| Shared subscription, 128 B JSON, ack each | 27,720 msg/s (27,716) | 27,662 msg/s (27,548) (indistinguishable over the client) | 27,710 msg/s (27,408) | indistinguishable (broker-bound) |
AMD Ryzen 9 7900X 12-Core Processor, x86_64, 427-5912 MHz, 12 physical, 24 logical, 62.4 GiB, unknown, Linux 7.2.11-x64v3-xanmod1-1, 1.99.0, 3.25.1, bench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only), ruststream-pulsar default (none), ruststream macros,json. ruststream-pulsar 0.7.0, ruststream 0.7.0, measured 2026-10-18.
Show the numbers as a table
| Scenario | Instructions | Allocations | Cold start |
|---|---|---|---|
| shared subscription, JSON decode into a small struct, ack each | 58,724.1 | 18.9 | 603,714 / 277 |
| reply through this crate's publisher, broker receipt awaited | 120,058.1 | 38 | 622,642 / 293 |
| shared subscription in batches of 64, assembled on the client | 59,643.5 | 18.2 | 614,552 / 281 |
The machine
| Processor | AMD Ryzen 9 7900X 12-Core Processor |
|---|---|
| Architecture | x86_64 |
| Frequency | 427-5912 MHz |
| Cores | 12 physical, 24 logical |
| Memory | 62.4 GiB |
| Memory speed | unknown |
| Operating system | Linux 7.2.11-x64v3-xanmod1-1 |
| Broker | apachepulsar/pulsar:4.1.2 in Docker on localhost |
| Round trip | 0.047 ms round trip |
| Compiler | 1.99.0 |
| Build profile | bench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only) |
| Features | ruststream-pulsar default (none), ruststream macros,json |
| RUSTFLAGS | none (the recipe clears RUSTFLAGS, so the numbers are not tied to this CPU) |
| Valgrind | 3.25.1 |
The numbers come from docs/benchmarks/results.json of this version, written by the benchmark
recipe. Methodology says how they were taken, and Numbers what
they allow you to conclude.