Performance & Interoperabilität
Ausschließlich unsere eigenen Messwerte, mit der Methodik dahinter — damit jede Zahl einzuordnen ist. Keine Marketing-Grafiken, keine extrapolierten Vergleiche: gemessen wird auf denselben Hosts, mit denselben Tools, gegen die etablierten DDS-Implementierungen.
Alle Latenz-Zahlen sind Roundtrips (Request → Response, halbiert ergibt sich die One-Way-Latenz nicht — wir berichten den vollen Roundtrip). Perzentile statt Mittelwert, weil bei Echtzeit-Systemen der Schwanz zählt. Wo nicht anders genannt: voller DCPS-Pfad (Discovery + RTPS + Reader/Writer-Matching), RELIABLE, KEEP_LAST(64), UDPv4 über Loopback, vanilla Linux ohne RT-Tuning — also der konservative Fall, nicht das getunte Schaufenster.
Roundtrip-Latenz im Vergleich von sechs Stacks
Selber Host, selbe Pipeline für alle sechs Stacks — jeder mit seinem eigenen Code-Generator und seiner nativen DCPS-API. Selbstpaar (Ping und Pong derselbe Stack), n=2000, RELIABLE, bester von fünf Runs, jedes Paar über UDPv4. Stand 02.10.2026.
| Stack | p50 | p90 | p99 | p99.9 | max | p50 8 KB | Transport |
|---|---|---|---|---|---|---|---|
| Cyclone DDS | 25.1 | 33.3 | 47.0 | 63.1 | 79.9 | 36.6 | UDPv4 |
| RTI Connext | 30.1 | 36.2 | 45.2 | 69.0 | 99.7 | 37.3 | UDPv4 |
| ZeroDDS | 32.6 | 35.8 | 46.8 | 56.4 | 60.0 | 41.9 | UDPv4 |
| Fast DDS | 41.4 | 55.4 | 72.0 | 88.6 | 89.8 | 42.4 | UDPv4 |
| OpenSplice CE | 68.1 | 77.1 | 97.3 | 121 | 145 | 117 | UDPv4, XCDR1 |
| OpenDDS | 200 | 311 | 351 | 445 | 479 | 317 | UDPv4 |
Values in µs. p50 = median. 0-Byte-Payload bis auf die Spalte „p50 8 KB“ (8192 Byte). Host: Linux-Container (LXC, AMD Threadripper PRO, 16 Threads), vanilla (kein PREEMPT_RT, kein CPU-Pinning). ZeroDDS läuft mit transport.same_host_shm=false: auch sein Selbstpaar geht über UDPv4 und nicht über ZeroDDS' Shared-Memory-Träger.
- Selbstpaar über UDPv4: ZeroDDS liegt beim p50 mit 32.6 µs hinter Cyclone (25.1) und RTI (30.1) und vor Fast DDS (41.4), OpenSplice und OpenDDS. Im p99 liegt es gleichauf mit Cyclone und RTI (46.8 µs), p99.9 und Maximum sind die kleinsten der sechs (56 und 60 µs).
- 8 KB zwischen verschiedenen Stacks: ZeroDDS ↔ Cyclone, Fast DDS und RTI 37–50 µs, zwischen diesen dreien 41–52 µs. Vor dieser Messung zerlegte ZeroDDS ein Sample an einen fremden Stack auf demselben Host in 1344-Byte-Fragmente, eins je Datagramm, und lag dort bei 64–83 µs; das ist behoben.
- Ehrlich: das ist Same-Host-Loopback ohne RT-Tuning. Getunte Zahlen veröffentlichen wir erst, wenn der RT-Aufbau steht.
Cross-Vendor-Interop
Volle 6×6-Roundtrip-Matrix: jeder Stack als Pinger gegen jeden als Ponger, echte Wire-Interop (Discovery + RTPS + QoS-Matching), nicht nur Discovery-Sichtbarkeit.
| Ping ↓ / Pong → | ZeroDDS | Cyclone | Fast DDS | RTI | OpenDDS | OpenSplice | Score |
|---|---|---|---|---|---|---|---|
| ZeroDDS | 33 | 36 | 34 | 37 | 76 | 60 | 6/6 ✅ |
| Cyclone | 34 | 25 | 40 | 32 | 71 | 44 | 6/6 ✅ |
| Fast DDS | 33 | 44 | 41 | 39 | 188 | 60 | 6/6 ✅ |
| RTI | 31 | 26 | 35 | 30 | — | · | 4/5 |
| OpenDDS | 66 | 76 | 130 | — | 200 | — | 4/6 |
| OpenSplice | 49 | 47 | 60 | · | — | 68 | 4/5 |
p50 µs, 0-Byte-Payload. 30 von 34 gemessenen Zellen grün; ZeroDDS matcht mit allen fünf anderen Stacks in beiden Richtungen. — = kein Match: RTI ↔ OpenDDS (OpenDDS zählt die Type-Consistency-Stufen ab 1 statt ab 0, liest RTIs ALLOW_TYPE_COERCION als DISALLOW_TYPE_COERCION und verlangt dann gleiche Minimal-Typ-Hashes, die RTI und OpenDDS verschieden bilden) und OpenDDS ↔ OpenSplice (OpenDDS verbindet einen Endpunkt erst, wenn dessen Teilnehmer die SEDP-Ankündigung bestätigt hat; bei OpenSplice tut das ein anderer Teilnehmer derselben Federation). · = mit unserer RTI-Lizenz nicht messbar: sie lässt höchstens 12 DataReader und 12 DataWriter zu, und OpenSplice kündigt mehr eigene an (RTI ↔ OpenSplice). Paare mit OpenSplice laufen in XCDR1, alle anderen in XCDR2.
ROS 2: rmw_zerodds ↔ rmw_cyclonedds Talker/Listener bidirektional 20/20 grün. Live-SPDP-Discovery erkennt Cyclone und Fast-DDS auf demselben Subnetz.
DDS-Security (Cross-Vendor, verschlüsselt)
Roundtrip mit eingeschaltetem data_protection=ENCRYPT (AES-GCM auf User-Payload), 64-Byte-Payload. Interessant ist der Crypto-Aufschlag relativ zur eigenen Plain-Baseline.
| Stack | Plain p50 | Encrypted p50 | Overhead |
|---|---|---|---|
| ZeroDDS | 25 | 65 | +40 µs absolut, sauberste Kurve |
| Cyclone | 36 | 44 | +22 % |
| Fast-DDS | 58 | 109 | +88 % |
| OpenDDS | ~90 | 132 | +47 % |
Cross-Vendor verschlüsselt: ZeroDDS matcht in beiden Richtungen über das volle 13-Profil-Governance-Spektrum — 13/13 mit Cyclone, 13/13 mit Fast-DDS, 9/13 mit OpenDDS (das ZeroDDS-Maximum; die vier Lücken sind OpenDDS-Spec-Grenzen, kein ZeroDDS-Bug). Die roten Zellen der Vollmatrix sind ausschließlich Fremd↔Fremd-Paare (Vendor-Löcher zwischen den anderen Stacks). Das ist echte 4-Vendor-DDS-Security-Interop auf User-Payload-Crypto-Ebene.
Rich-Typed XCDR2 — Member-Codec unter Last
Statt opaker Bytes ein maximal verschachtelter Typ: string<64>, double transform[16], sequence<Waypoint,32> (je 2 verschachtelte Vec3 + String + Skalare, 8 Waypoints/Sample). Das isoliert die XCDR2-Member-Codec-Arbeit vom Transport. p50 µs, Payload 64, Ping (Zeile) → Pong (Spalte); ✗ = NO_DATA.
| Ping ↓ / Pong → | ZeroDDS | Cyclone | Fast-DDS | RTI | OpenDDS |
|---|---|---|---|---|---|
| ZeroDDS | 20 | 41 | 35 | 61 | 60 |
| Cyclone | 62 | 70 | 77 | ✗ | ✗ |
| Fast-DDS | 70 | 91 | 64 | 76 | 123 |
| RTI | 23 | ✗ | 67 | 56 | ✗ |
| OpenDDS | 103 | ✗ | 79 | ✗ | 226 |
Values in µs. ZeroDDS interoperiert auf dem rich-Typ mit allen vier anderen Vendoren — neben Fast-DDS der einzige voll-verbundene Stack. Die Codec-Kosten (rich vs. basis) liegen im LXC-Rauschen, daher ist nur das Ranking belastbar, kein absoluter Codec-Vorsprung. Leere Zellen sind ausschließlich Fremd↔Fremd, kein ZeroDDS beteiligt: Cyclone, RTI und OpenDDS bilden für die verschachtelten Structs verschiedene Minimal-Typ-Hashes, und Cyclone wie OpenDDS lehnen die Zuweisbarkeit dann ab.
Verschlüsselt + rich (DDS-Security 1.2 + rich-Typ)
| Ping ↓ / Pong → | ZeroDDS | Cyclone | Fast-DDS | OpenDDS |
|---|---|---|---|---|
| ZeroDDS | 73 | 93 | 141 | 145 |
| Cyclone | 90 | 118 | ✗ | ✗ |
| Fast-DDS | 120 | ✗ | 176 | ✗ |
| OpenDDS | 143 | ✗ | ✗ | 181 |
Values in µs; RTI omitted (security licence not purchased). ZeroDDS interoperiert verschlüsselt + rich mit Cyclone, Fast-DDS und OpenDDS in beiden Richtungen, mit EC-P-256-Identitäten. Die Paare zwischen den anderen Stacks kommen nicht zustande (✗: kein Match in fünf Läufen). Security läuft über SRTPS-über-UDP (der SHM-Carrier wird bei aktiver Crypto umgangen). Jede Zelle ist der beste p50 von fünf Läufen; die Lastmittel des geteilten Hosts lagen während der Messung zwischen 4,5 und 12, im Mittel 7.
TSN — RTPS direkt über Ethernet
Roundtrip des Live-AF_PACKET-Transports (DDS-TSN Annex A, RTPS im Ethernet-Frame, EtherType 0x88B5) gegen eine UDP-Baseline über denselben Link.
| Transport | p50 | p90 | p99 | max | Jitter (p99−p50) |
|---|---|---|---|---|---|
| TSN / AF_PACKET 0x88B5 | 11.95 | 22.49 | 29.58 | 281 | 17.62 |
| UDP (same link) | 17.10 | 21.07 | 34.90 | 928 | 17.79 |
µs, 64-Byte-Payload. Der Raw-Ethernet-Pfad liegt unter UDP, weil er den IP/UDP-Stack umgeht.
Wichtig zur Einordnung: das ist eine Host-Pfad-Messung ohne TSN-Switch. Der eigentliche TSN-Vorteil — deterministische, eng begrenzte Latenz unter Last — entsteht im Netz (Time-Aware Shaper / gPTP), nicht im Host-Socket. Diese Zahl belegt nur, dass unser Ethernet-Transport keinen Overhead-Nachteil gegenüber UDP hat.
CORBA (Migrations-Pfad)
Für den CORBA-Koexistenz-Stack: IIOP-Roundtrip über TCP-Loopback gegen die etablierten ORBs, plus bidirektionale Cross-ORB-Interop.
| ORB | p50 (32 B) | Cross-ORB-Interop |
|---|---|---|
| ZeroDDS | 16.3 | schnellster ORB im Vergleich |
| omniORB | 17.9 | ✅ |
| TAO | 36.7 | ✅ |
| JacORB | 57.1 | ✅ inkl. Big-Endian-Konvertierung |
Alle sechs Client/Server-Kombinationen gegen omniORB, TAO und JacORB sind bidirektional grün (Echo + Bench), einschließlich Byte-Order-Konvertierung.
Microbenchmarks (Hot-Path)
Writer-Dispatch — die reine Sample-Send-Kette über RTPS, Criterion-gemessen. Zero-Copy-Fan-out über Arc<[u8]> (kein Payload-Kopieren beim Fan-out):
| Payload | Vec (copy) | Arc (zero-copy) | Δ |
|---|---|---|---|
| 64 B | 390 ns | 390 ns | ±0 % |
| 1 KB | 525 ns | 489 ns | −6.9 % |
| 4 KB | 959 ns | 974 ns | +1.6 % |
| 16 KB | 3.18 µs | 3.09 µs | −2.8 % |
| 64 KB | 11.49 µs | 11.04 µs | −3.9 % |
Methodik — wie gemessen wird
- Hosts: zwei Maschinen — ein Linux-Container (LXC, AMD Threadripper PRO) und ein Bare-Metal-Apple-M1. Jede Zahl nennt ihren Host.
- Atomic-Pipeline: frischer Prozess-Baum pro Matrix-Zelle, isolierte Domain-IDs, kein geteilter Shell-Zustand — keine Cross-Contamination zwischen Messungen.
- QoS: RELIABLE, KEEP_LAST(64), XCDR1/XCDR2, UDPv4 über Loopback (kein physisches Netz, also kein Switch-/Kabel-Jitter).
- Sampling: 200 Warmup + 2000 Messwerte pro Zelle; p50 ist der Median, robust gegen Einzel-Ausreißer. Roh-Histogramme im Repo.
- Tuning: vanilla, sofern nicht anders genannt — kein PREEMPT_RT, kein
isolcpus, keinchrt. Das ist bewusst der konservative Fall. - Hersteller-Versionen in Abschnitt 1 und 2: Cyclone DDS 11.0.1, Fast DDS 3.6.1, OpenDDS 3.34.0, OpenSplice CE 6.9.210323; RTI Connext 7.7.0 aus der Messung vom 23.05.2026. Jeder Stack über seinen eigenen Code-Generator und seine native DCPS-API.
Offene Punkte & Grenzen (ehrlich)
- RT-getunte Zahlen fehlen noch. Das sub-µs-Regime (PREEMPT_RT + Pinning) ist noch nicht reproduzierbar aufgebaut; die hier gezeigten Zahlen sind vanilla.
- RTI ↔ OpenDDS (23.05.) und OpenDDS ↔ OpenSplice (30.09.) matchen untereinander nicht — Lücken zwischen Fremd-Stacks; ZeroDDS matcht mit allen dreien.
- TSN cross-vendor über den 0x88B5-Ethernet-PSM ist heute nicht möglich: kein anderer Vendor liefert das OMG-Annex-A-Wireformat interoperabel aus.
- Kommerzielle Pro-Ligen (RTI Pro, Fast-DDS Pro mit Custom-Allocator/Lock-Free-Ring) messen wir bewusst nicht gegen — wir veröffentlichen keine unfairen Vergleiche. Siehe Hard Truths.
Reproduzierbarkeit
Alle Messungen sind reproduzierbar dokumentiert. Wenn du die Zahlen in deiner Umgebung nicht reproduzierst, ist das ein Issue wert. Roh-Daten und Skripte:
- tools/bench-suite — Criterion-Suite + Roundtrip-Binaries
- tests/perf — Roundtrip-Matrix, TSN-Latenz, Soak-Runner
- tests/interop — Cross-Vendor- und ROS-2-Interop-Harness
Weiter: Features · Hard Truths · Kontakt