Cloudflare a réalisé une économie d’environ 100 To de mémoire totale dans l’infrastructure exécutant sa plateforme DNS Big Pineapple, suite à une refonte de la manière dont elle représente et stocke en RAM les entrées de cache. Ce travail n’a pas consisté à ajouter des serveurs, mais à effectuer cinq modifications successives sur des structures de données écrites en Rust, réduisant ainsi de 56 % la taille mémoire par entrée tout en améliorant la performance du cache.
Les clés de l’optimisation de Cloudflare en 30 secondes
- Big Pineapple conserve plus de 250 000 milliards d’entrées DNS simultanément pour des services comme 1.1.1.1, Gateway DNS et DNS Firewall.
- La mémoire moyenne par entrée a été réduite de 953 à 420 octets, soit une baisse de 56 %.
- L’économie totale atteint environ 100 To de mémoire, équivalent à la RAM de près de 130 serveurs Gen 13 de l’entreprise.
- Le nombre d’insertion dans le cache a augmenté de 43 %, tandis que la latence de requête a diminué de 19 %.
- Une partie de ces gains provient de la réduction des allocations, de l’élimination de données redondantes et d’un stockage plus compact des enregistrements DNS.
Ce cas est particulièrement instructif pour les administrateurs systèmes et développeurs, car il montre à quel point quelques dizaines d’octets peuvent devenir critiques à grande échelle. Big Pineapple maintient plus de 250 milliards d’éléments en cache à tout moment. À ce volume, un seul octet inutile par entrée peut représenter plus de 250 Go de mémoire dépensée dans toute l’infrastructure.
Cloudflare a commencé à déployer ces modifications le 18 mai 2026, et a étendu leur application à tous les services le 6 juillet. Les résultats ont été mesurés à la fois via des benchmarks et en observant la consommation mémoire réelle des instances en production.
De Vec et String à des structures occupant exactement ce qui est nécessaire
Une entrée de cache DNS contient beaucoup plus d’informations qu’une simple adresse IP. Big Pineapple stocke la requête, le type d’enregistrement, des données d’authentification, les réponses DNS, les enregistrements d’autorité et des données additionnelles, ainsi que des métadonnées telles que le temps de création, le nombre d’accès et le TTL (Time To Live).
Une des premières améliorations est partie d’une caractéristique courante de Rust.
Un Vec<t> doit conserver trois données : un pointeur vers les éléments, sa longueur actuelle et sa capacité. Cette capacité supplémentaire est indispensable tant qu’une collection peut continuer à croître.
Le problème est que la réponse DNS stockée en cache chez Cloudflare ne change plus après insertion.
Maintenir une capacité pour de futurs éléments n’a donc pas de sens.
Cloudflare a remplacé plusieurs Vec<t> par des Box<[T]>, des structures de taille fixe qui ne nécessitent pas de capacité supplémentaire. La même idée a été appliquée aux chaînes de caractères, en remplaçant certains String par Box<str>.
Chaque entrée comportait huit de ces champs. En éliminant huit octets par champ, cela permet d’économiser 64 octets par entrée, en plus de l’espace que les vecteurs auraient pu réserver mais ne pas utiliser.
À l’échelle de la plateforme, ce changement représente only plus de 15 To de mémoire, selon les calculs de Cloudflare.
C’est un exemple parfait pour montrer comment l’analyse du coût en ressources d’un service à grande échelle doit considérer ces petits détails. Une structure raisonnable pour une application classique peut devenir excessive lorsqu’on doit gérer des centaines de milliards d’objets.
Moins de listes et moins de pointeurs
Cloudflare a également repensé comment stocker les trois sections principales d’une réponse DNS : réponse, autorité et données additionnelles.
Initialement, chaque section disposait de sa propre liste.
La nouvelle version utilise une collection unique de registres, avec de petits décalages pour indiquer où commence chaque section.
Puisque le nombre d’enregistrements peut être représenté par des valeurs u16, chaque décalage ne nécessite que deux octets.
Selon Cloudflare, cette modification permet d’économiser 28 octets par entrée en supprimant deux listes indépendantes avec leurs pointeurs et longueurs respectifs.
Elle exploite également des détails de programmation bas niveau. Rust ajoute de l’espace d’alignement (padding) pour maintenir correctement l’alignement de certains champs. Par conséquent, déplacer ou éliminer de petits champs peut en réalité faire économiser plus qu’on ne le pense en taille apparente.
Cloudflare a aussi regroupé plusieurs valeurs booléennes à l’aide de bitflags pour réduire l’espace utilisé.
Supprimer les données redondantes et réduire le coût des enum en Rust
Un autre changement s’est concentré sur le propriétaire de chaque enregistrement DNS.
Une requête pour un enregistrement A d’un domaine retourne souvent des enregistrements dont le propriétaire est identique au domaine demandé. Stocker à répétition ce nom dans chaque enregistrement est redondant, car cette information est déjà présente dans la clé du cache.
Cloudflare a choisi de ne pas stocker cette valeur lorsque le propriétaire correspond exactement au domaine d’origine.
Il conserve explicitement cette donnée seulement si elle diffère, par exemple après un suivi de CNAME.
Lorsque la réponse est reconstruite, Big Pineapple récupère le domaine original directement depuis la clé du cache, réduisant ainsi l’utilisation mémoire et le nombre d’allocations sur le heap, ce qui est bénéfique dans le cas le plus courant.
Une optimisation particulièrement liée à Rust consiste à gérer la taille des enum.
Un enum peut contenir des variantes de tailles très différentes, mais la structure doit réserver la taille de sa variante la plus volumineuse.
Cloudflare avait une représentation similaire à :
pub enum RecordData {
A(Ipv4Addr),
Aaaa(Ipv6Addr),
Txt(Txt),
Naptr(Naptr),
Svcb(Svcb),
}
Le problème venait de NAPTR.
Sa structure pouvait nécessiter environ 136 octets, portant la taille totale du enum à environ 144 octets (compte tenu de l’identificateur de variante et de l’alignement).
En réalité, un enregistrement IPv4 A ne nécessite que 4 octets, tandis qu’un AAAA utilise 16 octets.
Cette différence est essentielle car ces deux types représentent plus de 80 % du trafic DNS de Cloudflare en test.
Cela signifiait réserver plus de 120 octets d’espace inutile pour de nombreux enregistrements courants.
Box pour une partie du problème, mais créant un autre
Une première solution a été de conserver directement dans le enum les petits enregistrements, et de déplacer les grands enregistrements dans la mémoire dynamique via Box.
Le poids de la structure principale a ainsi considérablement diminué.
Mais un nouveau coût est apparu :
Chaque Box nécessite une allocation séparée dans le heap. Cloudflare utilise jemalloc, qui regroupe les allocations par classes de taille, ce qui peut entraîner une utilisation mémoire légèrement supérieure à la demande initiale.
Le problème le plus critique concerne la CPU :
En disséminant les données dans différentes zones du heap, le processeur doit suivre des pointeurs pour accéder à chaque enregistrement. Ces données peuvent être dispersées, augmentant ainsi le nombre d’accès aux lignes mémoire et dégradant la localité des données.
Ainsi, économiser de la mémoire pouvait nuire à la vitesse d’accès aux données.
Cloudflare a continué à rechercher une autre représentation.
Stocker en partie les données DNS tel que transitent sur le réseau, en améliorant mémoire et vitesse
La solution finale a été de s’approcher du format binaire utilisé par DNS lui-même.
La société a envisagé de stocker directement l’intégralité des réponses DNS en format wire, mais a renoncé en raison de complications que cela pourrait engendrer. La validation DNSSEC, la compression de noms et certains champs variables selon le client imposeraient de maintenir plusieurs représentations ou de retraiter toute la trame à chaque requête.
L’approche intermédiaire a été de stocker les données des enregistrements sous forme de bytes, en conservant le reste de l’entrée dans des champs structurés.
Au lieu d’un grand nombre d’enum et d’allocations séparées, tous les enregistrements sont stockés consécutivement dans un seul Box<[u8]>.
Chaque enregistrement inclut un préfixe de deux octets indiquant sa longueur, suivi de l’enregistrement codé.
Ce choix offre deux avantages majeurs :
- Premièrement, il élimine une bonne partie de l’overhead lié aux
enum, aux pointeurs et aux allocations individuelles. - Deuxièmement, il garantit que les données sont stockées de manière contiguë, améliorant la localité dans la mémoire cache du CPU.
Certes, Cloudflare sacrifie la possibilité d’un accès direct par index, devant parcourir séquentiellement le buffer.
Ce compromis est acceptable selon eux, car une réponse DNS ne contient que peu d’enregistrements en général.
De plus, certains types d’enregistrements peuvent être copiés presque directement depuis la cache vers la réponse DNS, comme A, AAAA, TXT ou certains DNSSEC. Les autres, tels que CNAME, NS, MX ou SOA, nécessitent encore un traitement pour la compression DNS des noms.
Selon Cloudflare, cette nouvelle organisation contribue à réduire la latence de requête d’environ 5 %.
Ils utilisent aussi un buffer temporaire réutilisable pour assembler les enregistrements avant stockage. Étant donné qu’il a déjà été agrandi lors d’opérations précédentes, il peut généralement être réutilisé sans allocations supplémentaires.
Selon leurs benchmarks, cette dernière optimisation augmente à elle seule la performance d’insertion dans le cache de 13 %.
De 953 à 420 octets par entrée
L’effet cumulatif des cinq optimisations est bien supérieur à la somme de leurs effets individuels.
| Indicateur | Avant | Après | Changement |
|---|---|---|---|
| Huella mémoire nette par entrée | 953 octets | 420 octets | -56 % |
| Mémoire allouée par entrée | 1,1 Ko | 461 octets | -58 % |
| Insertions dans le cache | 625 000/s | 893 000/s | +43 % |
| Latence de requête | 828 ns | 670 ns | -19 % |
Les résultats proviennent des benchmarks de Cloudflare, réalisés avec une simulation adaptée à leur trafic réel, utilisant 56 % d’enregistrements A, 25 % de AAAA et 19 % de TXT, avec de 1 à 4 enregistrements par entrée.
La société précise que ces tests ne reproduisent pas parfaitement la production. La consommation réelle dépend notamment de la mixture de trafic, de l’état du cache, de la gestion de la mémoire dynamique et autres facteurs.
Elle a aussi mesuré ses instances en conditions réelles :
Au 99e percentile, la mémoire résidente est tombée de 9,3 Go à 5,3 Go, soit une baisse de 43 %. Au 90e percentile, elle est passée de 6,5 Go à 3,8 Go, soit 42 % de réduction.
Après déploiement complet et stabilisation des caches, Cloudflare estime que la mémoire de travail totale a été réduite d’environ 100 To.
Ce montant correspond à la mémoire de près de 130 serveurs Gen 13.
Cependant, l’objectif n’est pas forcément de laisser ces 100 To inutilisés. Cloudflare prévoit de réinvestir une partie de cette capacité dans l’agrandissement de ses caches, sans augmenter leur consommation totale de RAM. L’idée étant d’améliorer le taux de réussite en cache et de réduire les requêtes vers des serveurs DNS externes.
L’exemple de Big Pineapple montre aussi une leçon concrète pour les services à grande échelle : le choix de la structure de données peut s’avérer aussi crucial que celui de l’algorithme.
Vec, String, enum ou Box ne sont ni intrinsèquement meilleurs ni pires ; leur coût dépend de leur utilisation, de leur temps de vie en mémoire et du volume d’objets simultanés.
Pour une application classique, économiser 64 octets peut ne pas justifier une refonte complète de la gestion mémoire. Mais avec 250 milliards d’entrées, ces mêmes 64 octets représentent plusieurs téraoctets.
Questions fréquentes
Comment Cloudflare a-t-il réussi à économiser 100 To de RAM ?
En modifiant la représentation en mémoire des entrées de son cache DNS, en réduisant les structures dynamiques, en éliminant les redondances, en réorganisant les enregistrements, et en stockant une partie sous forme binaire compacte.
Combien d’entrées DNS Cloudflare conserve-t-elle en cache ?
Plus de 250 000 milliards d’entrées, pour des services comme 1.1.1.1, Gateway DNS, DNS Firewall, et autres.
Ces optimisations ont-elles affecté la performance de 1.1.1.1 ?
Au contraire : selon les benchmarks, l’insertion dans le cache enregistre une hausse de 43 %, et la latence diminue de 19 %.
Que compte faire Cloudflare avec la mémoire libérée ?
L’entreprise prévoit d’utiliser une partie de cette capacité pour augmenter la taille de ses caches, sans augmenter leur consommation totale de RAM, afin d’améliorer leur efficacité et réduire les requêtes vers les serveurs DNS en amont.
Source : Cloudflare