Skip to main content

Benchmarks

What ruststream-gcp-pubsub costs on every message: throughput against the raw google-cloud-pubsub client, and instructions and allocations of its code.

Against a raw client​

The first chart runs each scenario three ways against the local Pub/Sub emulator. Raw client drives google-cloud-pubsub directly. Broker crate drives this crate and nothing above it: its subscription, the deliveries it yields and its publisher, pulled and settled by a loop with no service around it. RustStream is the service a user writes: a #[subscriber] handler, the app and the runtime. The first gap is what this crate costs over the client it wraps, and it is the number this repository answers for. The second is what the runtime adds on top, over Pub/Sub in particular.

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 second scenario publishes under ordering keys, the delivery shape a subscription with ordering enabled keeps in order per key. It also gives this crate one piece of work the first scenario does not have: the key is carried into the delivery's headers, where a service that names no broker reads it as a partition key. A loop on the client reads the field on the message and copies nothing.

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 the service a user writes, built on PubSubBroker and started against the emulator of the same stand. Everything on the service's thread is counted: the framework's dispatch, this crate's code and the google-cloud-pubsub client, whose streaming pull, acknowledgements, lease extensions and publish requests run there. Cold start is what starting the service and taking the first delivery cost once.

Most of every row is the client. The reply row is the largest: the runtime waits for each reply to be confirmed before it takes the next delivery, so every reply leaves in a publish request of its own. The cold start is almost all the client too: it builds two administration clients, each of which reads and parses the machine's root certificates, so that column depends on the machine's certificate store.

Results​

Against a raw clientHow far each loop falls below the raw client's best round
  • Raw client
  • Broker crate
  • RustStream
  • rounds, best to slowest
  • best round
  • median round
  • spread of the rounds
  • indistinguishable

ruststream-gcp-pubsub 0.7.0 on ruststream 0.7.0, AMD Ryzen 9 7900X 12-Core Processor, Linux 7.2.10-x64v3-xanmod1-1, Pub/Sub emulator, gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators, Google Cloud SDK 587.0.0, in Docker on localhost, measured 2026-10-18. How the numbers were taken

Streaming pull, 512 B JSON, ack each
  • indistinguishable
  • indistinguishable
Streaming pull with ordering keys, 512 B JSON, ack each
  • indistinguishable
  • indistinguishable (broker-bound)
Show the numbers as a table
ScenarioRaw clientBroker crateRustStreamOverhead
Streaming pull, 512 B JSON, ack each1,815 msg/s (1,807)1,805 msg/s (1,803) (indistinguishable over the client)1,819 msg/s (1,809)indistinguishable
Streaming pull with ordering keys, 512 B JSON, ack each1,987 msg/s (1,986)1,987 msg/s (1,986) (indistinguishable over the client)1,988 msg/s (1,988)indistinguishable (broker-bound)
Cost of the code

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-gcp-pubsub default (none), ruststream macros,json; google-cloud-pubsub 1.3.0. ruststream-gcp-pubsub 0.7.0, ruststream 0.7.0, measured 2026-10-18.

Instructions
Allocations
consume, JSON decode into a small struct, ack each
10,571
5.4
reply to a declared topic, each confirmed before the next delivery
106,926.5
88.3
consume in batches of 64, assembled on the client
10,809.5
5.5
Show the numbers as a table
ScenarioInstructionsAllocationsCold start
consume, JSON decode into a small struct, ack each10,5715.487,632,378 / 7,653
reply to a declared topic, each confirmed before the next delivery106,926.588.387,639,206 / 7,680
consume in batches of 64, assembled on the client10,809.55.587,640,196 / 7,657

The machine​

ProcessorAMD Ryzen 9 7900X 12-Core Processor
Architecturex86_64
Frequency427-5912 MHz
Cores12 physical, 24 logical
Memory62.4 GiB
Memory speedunknown
Operating systemLinux 7.2.10-x64v3-xanmod1-1
BrokerPub/Sub emulator, gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators, Google Cloud SDK 587.0.0, in Docker on localhost
Round trip0.269 ms (20000 GetSubscription calls on one connection); a delivery is charged 1 of them
Compiler1.99.0
Build profilebench, inheriting release (opt-level = 3, lto = fat, codegen-units = 16, debug = line-tables-only)
Featuresruststream-gcp-pubsub default (none), ruststream macros,json; google-cloud-pubsub 1.3.0
RUSTFLAGSnone (the recipe clears RUSTFLAGS, so the numbers are not tied to this CPU)
Valgrind3.25.1

The build flags are published with the numbers because they change them: a binary built with -C target-cpu=native produces a figure no other machine can reproduce, so the recipe clears the variable before it builds.

The numbers come from docs/benchmarks/results.json of this version, written by the benchmark recipe. The framework's site reads the same document, published at benchmarks/results.json, to build its table across brokers. Methodology says how the numbers were taken, and Numbers what they allow you to conclude.