MQTT and Sparkplug B

MQTT and Sparkplug B

Open in ChatGPT
Ask ChatGPT about this page
Open in Claude
Ask Claude about this page

Footprint

Footprint

What this library costs in flash and in RAM, measured rather than claimed.

Measured on 2026-10-04, by the footprint script in the
development tree - never typed in by hand.
Compiler: c++ (Ubuntu 15.2.0-16ubuntu1) 15.2.0.

Figures are .text plus read-only data of the static library, built
-Os with no sanitizers - the code and constants that land in flash.
RAM is measured separately, further down.

These are HOST builds, and a board build is smaller. The host
client links MqttTcpTransport (BSD sockets, a background DNS lookup)
and the host-only buffer growth in MqttLink (MQTT_LINK_GROWS, for a
broker holding many idle connections); a board links neither - it uses
MqttStreamTransport over its own network client, and fixed buffers.
Measured 2026-10-04: buffer growth alone is about 1 kB of the long form.

Flash
the whole library - client, broker, bridge, typed layer, Sparkplug 230079

What this means

That is one number because there is one build. There are no
feature flags: the client, the broker, the bridge and the typed layer
are all compiled, always. This table used to have seven rows - client,
client+tls, client+broker and so on - and every one of them measured
the same figure, because the flags they switched had already been
deleted. A table of seven identical numbers is worse than one honest
one.

What you pay is decided at LINK time, not compile time. A role you
never instantiate is a class nothing references, and the linker drops
it - which is measured below for MqttDevice rather than asserted,
down to checking that no symbol of it survives into a program that
does not name it. The same mechanism is what keeps the broker out of
a sketch that only publishes.

Two things this number does not include: TLS, which lives in whatever
engine you link (wolfSSL or OpenSSL) and not in here, and the buffers,
which are RAM and are below.

RAM

Flash is the table above; RAM is usually what a board runs out of
first. These are sizeof on the measuring host - a 32-bit target
is meaningfully smaller
, because every std::string and
std::vector inside them is.

MqttClient 13080 bytes
MqttDevice 22160 bytes
MqttOperations (the send queue) 3648 bytes
MqttSession 1336 bytes
one queue slot (MqttOperation) 112 bytes
one property set (MqttOwnedProperties) 144 bytes

The buffers are on top of this and are yours to size.
bufferSize() allocates a receive buffer and a transmit buffer -
so 4096 costs about 8 kB, and that is the single biggest number on a
small board. It used to be three buffers and about 12 kB; packets are
now encoded straight into the transmit queue instead of into a
scratch area and copied, which gave one of them back. See What a
large payload costs
in api.md.

A queue slot is smaller than a property set, which it can only be
because 5.0 properties are held behind a pointer. Inline they cost
MQTT_QUEUE_CAPACITY of them on every client, used or not - 4,608
bytes, measured, before this was fixed. The script fails if that
ever comes back.

What MqttDevice costs

The table above is the whole static library. An application links only
what it reaches, PROVIDED the build discards what it does not:
-ffunction-sections -fdata-sections when compiling and
-Wl,--gc-sections when linking. Arduino's own build recipes do this
and so does the measurement below - check your own platform.txt if
you are on a core this library has not been built for.

Measured rather than asserted: two programs, one written against
MqttClient and one against MqttDevice, linked and compared.

MqttClient, long form 48616 bytes
MqttDevice, short form 64320 bytes
the facade costs 15704 bytes

That buys the subscription table, per-filter routing, the change
reporter, the NUL-terminated payload copy, the conversions on it -
and the three transports the facade holds by value, so that
secure() is one call rather than a rebuild. The long form names
one transport and links one.

Formatting numbers as text is a small part of it, measured rather
than guessed: the same program publishing a string instead of a
float is 64 bytes smaller, because strtod is already
linked for toNumber().

And the other half of the claim is checked rather than asserted: the
long-form program's symbol table contains no MqttDevice symbols at
all
. A sketch that does not use the facade does not carry it.

Last updated 2 hours ago
Was this helpful?
Thanks!