Cloudflare gab die Ergebnisse einer Reihe von Optimierungen auf niedriger Ebene am DNS-Speicher der Big-Pineapple-Plattform bekannt. Diese Plattform betreibt 1.1.1.1, DNS Gateway, DNS Firewall, AS112 und eine Reihe weiterer DNS-Dienste. Die Plattform speichert jederzeit mehr als 250 Milliarden DNS-Einträge. Daher spart jedes eingesparte Byte pro Eintrag auf Flottenebene mehr als 250 Gigabyte Speicher.
Fünf aufeinanderfolgende Änderungen an der in Rust geschriebenen Datenstruktur senkten die Größe eines einzelnen Eintrags von 953 Byte auf 420 Byte, also um 56 %. Nach der flächendeckenden Einführung der Änderungen sank der von der Arbeitsmenge genutzte Speicher in der Cloudflare-Flotte um rund 100 Terabyte. Gleichzeitig verbesserte sich die Leistung, statt dass Einbußen hingenommen werden mussten: Die Einfügegeschwindigkeit stieg um 43 %, während die Suchlatenz im Speicher um 19 % sank.
Warum war die Größe eines DNS-Eintrags wichtig?
Big Pineapple startet mit einem leeren Speicher. Dieser füllt sich mit dem Eintreffen von Anfragen, bis die maximale Größe erreicht ist; anschließend werden die ältesten oder am wenigsten genutzten Einträge entfernt. Die Größe des Speichers unterscheidet sich zwischen den Rechenzentren. Außerdem kann die Verwendung von EDNS Client Subnet dazu führen, dass mehrere Antworten auf dieselbe Anfrage gespeichert werden, da autoritative Nameserver abhängig vom Netzwerk des Clients unterschiedliche Antworten liefern können.
Jeder Eintrag besteht aus einem Schlüssel, der den Domainnamen, den Datensatztyp und einige Eigenschaften festlegt, sowie einem Wert, der eine DNS-Antwort, die Authority- und Additional-Abschnitte und Metadaten wie Erstellungszeit, Nutzungszähler und TTL enthält. Bei dieser Größenordnung sind überflüssige Felder oder reservierter Speicherplatz keine kleinen internen Details mehr, sondern werden zu enormen Betriebskosten.
Woher kamen die Einsparungen?
Cloudflare ersetzte die dynamisch erweiterbaren Strukturen Vec und String durch feste Strukturen, nämlich Box<[T]> und Box<str>, nachdem die Antwort gespeichert worden war, da die Daten anschließend nicht mehr verändert werden. Dadurch entfiel das Kapazitätsfeld, das dynamisch erweiterbare Strukturen vorhalten, und auch der ungenutzte reservierte Speicherplatz wurde begrenzt. Da jeder Eintrag acht Felder dieser Art enthält, ergab sich eine Einsparung von 64 Byte pro Eintrag und von mehr als 15 Terabyte über den gesamten Speicher hinweg.
Außerdem wurden die Listen der Answer-, Authority- und Additional-Abschnitte in einer einzigen Liste zusammengeführt, wobei Offsets vom Typ u16 anstelle größerer Zeiger und Längen verwendet wurden. Dadurch konnten 28 Byte pro Eintrag eingespart werden. Die Struktur profitierte zudem davon, mehrere boolesche Felder in einem einzigen Bitflag zu bündeln, wodurch der durch die von Rust innerhalb der Strukturen vorgeschriebene Speicherausrichtung verschwendete Platz reduziert wurde.
Bei den meisten DNS-Datensätzen entspricht der Eigentümer des Datensatzes der Domain, nach der gefragt wurde. Deshalb speichert Cloudflare den vollständigen Eigentümernamen in diesen Fällen nicht mehr, sondern rekonstruiert ihn beim Erstellen der Antwort aus dem Speicherschlüssel. Wenn der Name abweicht, wie bei CNAME-Datensätzen, wird der vollständige Name gespeichert. Dadurch entfielen Speicherzuweisungen für die meisten Eigentümernamen, während die Fälle beibehalten wurden, in denen der Name tatsächlich benötigt wird.
Die Kosten großer Datensatztypen reduzieren
Die RecordData-Struktur verwendete ein Enum, dessen Größe der des größten Datensatztyps entsprach: NAPTR benötigte unter Einbeziehung von Tag und Ausrichtung 144 Byte. Infolgedessen belegten A-Datensätze, die nur 4 Byte benötigen, und AAAA-Datensätze, die 16 Byte benötigen, deutlich mehr Speicher als erforderlich, obwohl A und AAAA mehr als 80 % des Testdatenverkehrs ausmachten.
Es wurde versucht, die großen Typen in einer separaten Box abzulegen. Das verringerte zwar die Verschwendung bei A- und AAAA-Datensätzen, führte aber zu separaten Speicherzuweisungen und Problemen mit der Speicherlokalität. Die endgültige Lösung bestand darin, die Datensatzdaten selbst als zusammenhängende Rohbytes in einer Box<[u8]> zu speichern, mit einem zweibytigen Längenpräfix für jeden Datensatz. Dadurch entfielen die Kosten des Enums und der mehrfachen Speicherzuweisungen, und der Prozessor konnte den Cache-Speicher besser nutzen.
Diese Entscheidung bedeutet, dass die Datensätze nicht mehr per Zufallszugriff indiziert werden können, sondern sequenziell durchlaufen werden müssen. Cloudflare ist der Ansicht, dass die Kosten begrenzt sind, weil die Anzahl der Datensätze pro Eintrag gering ist. Die meisten Typen, darunter A, AAAA, TXT und DNSSEC-Datensätze, können außerdem direkt in die ausgehende DNS-Nachricht kopiert werden. Typen mit Domainnamen wie CNAME, NS, MX und SOA müssen dagegen weiterhin analysiert werden, um die DNS-Namenskomprimierung anzuwenden.
Was änderte sich in der Praxis?
Produktionsmessungen zeigten, dass der residente Speicher am 99. Perzentil von 9,3 auf 5,3 Gigabyte sank, also um 43 %, und am 90. Perzentil von 6,5 auf 3,8 Gigabyte, also um 42 %. Die Speicherzuweisungen pro Eintrag gingen von 1,1 Kilobyte auf 461 Byte zurück. Gleichzeitig stieg die Einfügegeschwindigkeit von 625.000 Einträgen pro Sekunde auf 893.000, während die Suchlatenz von 828 Nanosekunden auf 670 Nanosekunden sank.
Die Einführung der Änderungen begann am 18. Mai 2026 und war am 6. Juli 2026 über alle Dienste hinweg abgeschlossen. Cloudflare weist darauf hin, dass der residente Produktionsspeicher neben dem Speicher auch andere Daten umfasst. Daher fiel der tatsächliche Rückgang auf Prozessebene geringer aus als das Ergebnis der isolierten Messung pro Eintrag. Das Unternehmen plant außerdem, den freigewordenen Speicher wieder zu investieren, um die Speicherkapazität zu erhöhen, ohne den Speicherverbrauch zu steigern. Ziel ist es, die Cache-Trefferraten zu verbessern und die an übergeordnete Nameserver gesendeten Anfragen zu reduzieren.
Die Bedeutung dieses Falls liegt darin, dass er zeigt, dass Verbesserungen an Datenstrukturen wie das Entfernen unnötiger Kapazität, das Bündeln von Speicherzuweisungen und die Verbesserung der Speicherlokalität eine größere Wirkung erzielen können als die direkte Erweiterung von Hardware-Ressourcen, wenn ein Dienst mit Hunderten Milliarden Elementen arbeitet. Einige Abwägungen bleiben jedoch bestehen: Die Rohspeicherung erhöht die Komplexität bei der Verarbeitung der Datensätze, für die Rekonstruktion der Eigentümernamen wird der Zugriff auf den Speicherschlüssel erforderlich, und die Testergebnisse basieren auf einer bestimmten Verkehrsmischung, die nicht vollständig der Produktion entspricht. Daher bleiben Produktionsmessungen und nicht allein theoretische Zahlen die wichtigste Referenz bei der Bewertung solcher Optimierungen.