Benchmarks
What ruststream-rumqttc costs on every message: throughput against the raw rumqttc client,
and instructions and allocations of its code.
Against a raw client
The first chart runs each scenario three ways on a real MQTT server. Raw client drives
rumqttc 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 are the two qualities of service a service reads at. At QoS 0 the server sends each message and settles nothing. At QoS 1 the service acknowledges each delivery with a PUBACK, as Path draws.
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
MqttBroker reading a QoS 1 topic on the same server. The
service runs on one thread, and the task that polls the rumqttc event loop runs there too, so the
count holds the framework, this crate and the client's own work on the socket, the PUBACK included.
The producer's thread 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-rumqttc 0.7.0 on ruststream 0.7.0, AMD Ryzen 9 7900X 12-Core Processor, Linux 7.2.11-x64v3-xanmod1-1, eclipse-mosquitto:2 in Docker on localhost, measured 2026-10-18. How the numbers were taken
- indistinguishable
- indistinguishable
- indistinguishable
- indistinguishable (broker-bound)
Show the numbers as a table
| Scenario | Raw client | Broker crate | RustStream | Overhead |
|---|---|---|---|---|
| QoS 0 topic, 512 B JSON | 154,259 msg/s (151,130) | 152,504 msg/s (137,593) (indistinguishable over the client) | 153,188 msg/s (151,410) | indistinguishable |
| QoS 1 topic, 512 B JSON, ack each | 118,899 msg/s (118,745) | 117,722 msg/s (116,990) (indistinguishable over the client) | 118,792 msg/s (116,403) | 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-rumqttc default (none), ruststream macros,json. ruststream-rumqttc 0.7.0, ruststream 0.7.0, measured 2026-10-18.
Show the numbers as a table
| Scenario | Instructions | Allocations | Cold start |
|---|---|---|---|
| QoS 1 topic, JSON decode into a small struct, ack each | 8,769.5 | 1.2 | 3,820,572 / 67 |
| QoS 1 topic, reply published through this crate's publisher | 17,331.2 | 7.2 | 3,828,301 / 74 |
| QoS 1 topic, batches of 64 assembled on the client | 9,087.7 | 1.2 | 3,827,348 / 71 |
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 | eclipse-mosquitto:2 in Docker on localhost |
| Round trip | 41.8 microseconds, measured as a QoS 1 publish whose PUBACK the client waits for, averaged over 20,000 exchanges on a connection of its own |
| Compiler | 1.99.0 |
| Build profile | bench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only) |
| Features | ruststream-rumqttc default (none), ruststream macros,json |
| RUSTFLAGS | none (the recipe clears RUSTFLAGS, so the numbers are not tied to this CPU) |
| Load average | 9.15 / 10.95 / 9.58 over 1, 5 and 15 minutes when the run ended |
| 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.