Benchmarks
What ruststream-rdkafka costs on every message: throughput against the raw rdkafka client, and
instructions and allocations of its code.
Against a raw client
The first chart runs one scenario three ways on a real Kafka broker. Raw client drives a
librdkafka consumer 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 what an ack means. Under auto-commit librdkafka stores the offset when it
hands the record over, and an ack is advisory. Under Commit::Tracked every ack stores an offset,
as Settlement 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
KafkaBroker against the same broker. The count includes the framework's dispatch, this crate's
code and the librdkafka calls made on that thread. Fetching, the group protocol, producing and
delivery reports run on librdkafka's own threads and are not counted. Cold start is what starting
the service, joining the group and taking the first record cost once.
Results
- Raw client
- Broker crate
- RustStream
- rounds, best to slowest
- best round
- median round
- spread of the rounds
- indistinguishable
ruststream-rdkafka 0.7.0 on ruststream 0.7.2, AMD Ryzen 9 7900X 12-Core Processor, Linux 7.2.10-x64v3-xanmod1-1, apache/kafka:4.0.0 in Docker on localhost, measured 2026-10-17. How the numbers were taken
- indistinguishable
- indistinguishable
- +15.4%
- indistinguishable
Show the numbers as a table
| Scenario | Raw client | Broker crate | RustStream | Overhead |
|---|---|---|---|---|
| consumer group, auto-commit, 512 B JSON | 1,610,947 msg/s (1,492,199) | 1,543,835 msg/s (1,459,819) (indistinguishable over the client) | 1,411,671 msg/s (1,270,883) | indistinguishable |
| consumer group, tracked commits, 512 B JSON, ack each | 1,615,939 msg/s (1,603,120) | 1,366,726 msg/s (1,317,848) (+15.4% over the client) | 1,429,085 msg/s (1,324,713) | indistinguishable |
AMD Ryzen 9 7900X 12-Core Processor, x86_64, 427-5912 MHz, 12 physical, 24 logical, 62.4 GiB, unknown, Linux 7.2.10-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-rdkafka default (json), ruststream macros,json. ruststream-rdkafka 0.7.0, ruststream 0.7.2, measured 2026-10-17.
Show the numbers as a table
| Scenario | Instructions | Allocations | Cold start |
|---|---|---|---|
| consumer group, JSON decode into a small struct, ack each | 3,114.2 | 1 | 978,377 / 276 |
| reply through this crate's publisher, delivery report awaited | 7,823.8 | 5 | 1,310,777 / 372 |
| consumer group in batches of 64, from what librdkafka fetched | 3,176.4 | 1 | 977,306 / 277 |
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.10-x64v3-xanmod1-1 |
| Broker | apache/kafka:4.0.0 in Docker on localhost |
| Compiler | 1.99.0 |
| Build profile | bench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only) |
| Features | ruststream-rdkafka default (json), ruststream macros,json |
| RUSTFLAGS | none (the recipe clears RUSTFLAGS, so the numbers are not tied to this CPU) |
| Round trip | 78 µs (one metadata request and its answer) |
| 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.