Memory Footprint¶
This page shows how much memory a Python process uses after importing autobahn, compared with the frameworks and libraries it builds on, for CPython and PyPy. It helps to see what a given use of autobahn costs, and it documents how that cost changed across releases.
Background¶
Since 25.12.1, autobahn includes its own copy of the
FlatBuffers runtime, which it needs for WAMP
FlatBuffers serialization (before that, flatbuffers was an optional dependency,
the serialization extra). That runtime imports numpy at module level whenever
numpy is installed. Up to 26.7.1, autobahn imported the runtime eagerly, so every
process that imported autobahn also loaded numpy - including processes that use
only WebSocket, not WAMP, such as Django Channels applications served by
Daphne [1]. See issue #1983.
Since then, the goals are:
The autobahn package, and the wheels we build, include the vendored FlatBuffers runtime, including reflection.
For an application that depends on both autobahn and zlmdb, both of which vendor FlatBuffers, such as Crossbar.io, the two vendored versions are exactly the same:
autobahn.check_zlmdb_flatbuffers_version_in_sync()checks that.A user of autobahn who uses WebSocket only, not WAMP, with either Twisted or asyncio, loads no FlatBuffers code and no numpy.
autobahn now loads the FlatBuffers runtime only when a FlatBuffers message is first built or parsed.
What is measured¶
Each row is one import, run in a fresh interpreter. The value is the peak resident
set size of that process right after the import, in MB (MiB): VmHWM from
/proc/self/status on Linux. It is the memory the import costs at least, not the
memory a running application uses under load.
(ru_maxrss from resource.getrusage() would be the obvious choice, but on
Linux it carries over the peak memory of the process that started the measured one,
so for a child of a Python process it never drops below that parent’s size.)
Every venv has numpy installed, so the tables show whether an import loads it. A value marked † means numpy was loaded by that import.
Each import runs once as a warm-up (which may compile
.pycfiles) and is then measured 5 times; the table shows the median.Each autobahn version is measured in its own fresh venv, together with Twisted, cryptography, numpy and Daphne. The rows that do not involve autobahn are measured in every venv, so their spread across the columns shows the measurement noise.
Crossbar.io [2] is measured in a separate venv per autobahn version, with crossbar 26.7.1 from PyPI. No crossbar release supports autobahn 25.10.2, hence “n/a”.
Columns: 25.10.2 is the last release with FlatBuffers as an optional dependency, measured without that extra (as Daphne installs it). 26.7.1 is the last release that loaded the FlatBuffers runtime on import. 26.10.1 loads it on first use (#1983).
CPython 3.14¶
group |
import |
25.10.2 |
26.7.1 |
26.10.1 |
|---|---|---|---|---|
interpreter |
|
12.0 MB |
12.0 MB |
12.0 MB |
cryptography |
|
12.0 MB |
12.0 MB |
12.1 MB |
|
20.0 MB |
19.9 MB |
19.9 MB |
|
numpy |
|
28.5 MB † |
28.5 MB † |
28.6 MB † |
asyncio |
|
18.2 MB |
18.2 MB |
18.2 MB |
twisted |
|
43.5 MB |
43.5 MB |
43.5 MB |
txaio |
|
12.1 MB |
12.1 MB |
12.1 MB |
|
18.3 MB |
18.3 MB |
18.4 MB |
|
|
26.6 MB |
26.6 MB |
26.6 MB |
|
autobahn |
|
12.1 MB |
28.9 MB † |
12.1 MB |
|
32.0 MB |
47.8 MB † |
33.3 MB |
|
|
38.6 MB |
52.9 MB † |
39.9 MB |
|
|
36.3 MB |
51.2 MB † |
38.0 MB |
|
|
49.0 MB |
63.3 MB † |
50.4 MB |
|
daphne |
|
50.4 MB |
64.8 MB † |
51.8 MB |
crossbar |
|
n/a |
145.2 MB † |
145.2 MB † |
25.10.2 (venv): autobahn 25.10.2, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.5.4, daphne 4.2.3
26.7.1 (venv): autobahn 26.7.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.5.4, cbor2 6.1.5, daphne 4.2.3
26.7.1 (crossbar venv): autobahn 26.7.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.5.4, cbor2 6.1.5, crossbar 26.7.1, zlmdb 26.10.1
26.10.1 (venv): autobahn 26.10.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.5.4, cbor2 6.1.5, daphne 4.2.3
26.10.1 (crossbar venv): autobahn 26.10.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.5.4, cbor2 6.1.5, crossbar 26.7.1, zlmdb 26.10.1
Interpreter: CPython 3.14.7 (3.14.7 (main, Sep 1 2026, 14:18:09) [Clang 22.1.3 ]); Linux 6.12.95+deb12-amd64 x86_64, median of 5 runs.
PyPy 3.11¶
PyPy is a different runtime (a tracing JIT compiler with its own garbage collector), so compare these values with each other, not with the CPython table. On PyPy, the venvs use numpy 2.4.x, the last numpy release with PyPy wheels.
group |
import |
25.10.2 |
26.7.1 |
26.10.1 |
|---|---|---|---|---|
interpreter |
|
65.0 MB |
64.9 MB |
64.9 MB |
cryptography |
|
64.9 MB |
65.0 MB |
65.0 MB |
|
72.5 MB |
72.7 MB |
72.7 MB |
|
numpy |
|
88.9 MB † |
88.8 MB † |
88.8 MB † |
asyncio |
|
79.5 MB |
79.5 MB |
79.4 MB |
twisted |
|
106.8 MB |
106.8 MB |
106.8 MB |
txaio |
|
65.0 MB |
65.0 MB |
65.0 MB |
|
79.8 MB |
79.7 MB |
79.8 MB |
|
|
88.7 MB |
88.7 MB |
88.8 MB |
|
autobahn |
|
64.9 MB |
88.7 MB † |
65.0 MB |
|
93.8 MB |
113.0 MB † |
94.4 MB |
|
|
100.8 MB |
119.7 MB † |
101.3 MB |
|
|
99.1 MB |
117.9 MB † |
99.8 MB |
|
|
114.0 MB |
134.4 MB † |
114.6 MB |
|
daphne |
|
115.6 MB |
136.5 MB † |
116.3 MB |
crossbar |
|
n/a |
240.6 MB † |
216.5 MB † |
25.10.2 (venv): autobahn 25.10.2, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.4.6, daphne 4.2.3
26.7.1 (venv): autobahn 26.7.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.4.6, cbor2 6.1.5, daphne 4.2.3
26.7.1 (crossbar venv): autobahn 26.7.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.4.6, cbor2 6.1.5, crossbar 26.7.1, zlmdb 26.7.1
26.10.1 (venv): autobahn 26.10.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.4.6, cbor2 5.9.0, daphne 4.2.3
26.10.1 (crossbar venv): autobahn 26.10.1, txaio 26.6.1, twisted 26.4.0, cryptography 50.0.2, numpy 2.4.6, cbor2 5.9.0, crossbar 26.7.1, zlmdb 26.10.1
Interpreter: PyPy 3.11.15 (3.11.15 (194f9f44b505, May 25 2026, 19:34:11) [PyPy 7.3.23 with GCC 10.2.1 20210130 (Red Hat 10.2.1-11)]); Linux 6.12.95+deb12-amd64 x86_64, median of 5 runs.
Findings¶
26.10.1: every row that imports autobahn drops by about 13-17 MB on CPython, and by about 18-24 MB on PyPy, and none of them loads numpy any more. For example,
from daphne.server import Serverdrops from 64.8 MB to 51.8 MB on CPython 3.14, andimport autobahnalone is back to the size of the bare interpreter.Compared with 25.10.2: the WebSocket and WAMP rows remain about 1.2-1.6 MB above 25.10.2 on CPython (about 0.5-0.6 MB on PyPy). In 25.10.2 without the
serializationextra, cbor2 was not installed and the WAMP message module skipped that import. Since 26.x, cbor2 is a regular dependency.WebSocket only: with Twisted, most of what remains is Twisted itself; with asyncio, the asyncio standard library.
Twisted and cryptography:
import autobahn.twisted.websocketstill loads the nativecryptographybindings (about 8 MB on CPython), becauseautobahn/twisted/__init__.pyimportsautobahn.twisted.wamp, which importsautobahn.wamp.auth. A pure WebSocket user does not need them.import cryptographyalone costs next to nothing; the cost comes with the native bindings (from cryptography.hazmat.primitives import hashes).WAMP: WAMP users still load the FlatBuffers runtime (and numpy, if installed) as soon as they import
autobahn.wamp.serializer, also when they use another serializer.Crossbar.io loads numpy itself, so its router worker loads it regardless of this change; on CPython, its footprint is unchanged. On PyPy, the crossbar row comes out about 16 MB lower with this change, in repeated measurements, but we have not analysed why. Two things to keep in mind: on PyPy, the samples of a single import can spread by about 10 MB from run to run (garbage collection and JIT timing), and the two crossbar venvs differ in more than autobahn: on PyPy, autobahn 26.7.1 installs cbor2 6.x, while the development version installs cbor2 5.9.0 (see the versions below the PyPy table).
Reproducing¶
The scripts are in scripts/memory-footprint/. They create throwaway venvs with uv, measure, and regenerate the tables on this page:
just memory-footprint cpy314
just memory-footprint pypy311
measure.py alone measures the venv it runs in, e.g. for your own environment:
python scripts/memory-footprint/measure.py --variant mine
Footnotes