veilletech.fr
28 août Feed du jour
#03 CLOUDFLARE Article

Cloudflare : 100 To de RAM récupérés sur 1.1.1.1

Le meilleur profilage commence par la taille d'une structure.

Cloudflare détaille cinq changements de représentation mémoire dans le cache DNS de 1.1.1.1, sans toucher aux algorithmes : l'empreinte par entrée passe de 953 à 420 octets. Sur 250 milliards d'entrées, cela libère environ 100 To de RAM et accélère au passage les insertions comme les lectures.

3 min de lecturevidéo 1:17
Partager
Sommaire4 sections
  1. Ce qui se passe
  2. Les cinq changements
  3. Les résultats
  4. À retenir

Ce qui se passe

Big Pineapple, la plateforme Rust derrière 1.1.1.1, Gateway DNS, DNS Firewall et AS112, garde en permanence plus de 250 milliards d'entrées de cache DNS. À cette échelle, un octet gaspillé par entrée coûte 250 Go sur la flotte. Cinq changements successifs de représentation en mémoire ont divisé l'empreinte par plus de deux, sans modifier un seul algorithme.

Les cinq changements

1. Supprimer la capacité. Un Vec<T> porte trois champs : pointeur, longueur et capacité. Une réponse DNS mise en cache n'est plus jamais modifiée, donc la capacité ne sert à rien — 8 octets par champ, plus l'espace sur le tas réservé « au cas où ». Box<[T]> et Box<str> s'en passent. Huit champs par entrée : 64 octets, soit plus de 15 To à l'échelle de la flotte.

2. Une liste au lieu de trois. Les sections answer, authority et additional deviennent une liste unique avec deux décalages u16, puisqu'un compte d'enregistrements tient sur 16 bits. Deux pointeurs et deux longueurs de 8 octets remplacés par 2 + 2 octets : 28 octets par entrée. Les booléens regroupés en bitflags font gagner davantage que leur taille, en supprimant du remplissage d'alignement.

3. Ne plus stocker le propriétaire quand il est déductible. Le owner d'un enregistrement est presque toujours le domaine interrogé — sauf derrière un CNAME. Il devient optionnel, et la clé de cache, déjà disponible à chaque lecture, le restitue :

Rust
pub struct Record {
    owner: Option<Box<Name>>,
    class: Class,
    ttl: Ttl,
    rtype: Rtype,
    data: RecordData,
}

4. Boxer les grandes variantes. Une énumération Rust fait toujours la taille de sa plus grande variante : ici NAPTR, 136 octets, soit 144 avec le tag et le remplissage. Or un A tient sur 4 octets, un AAAA sur 16, et ces deux types représentent plus de 80 % du trafic — 120 octets perdus par enregistrement. Déplacer Txt, Naptr et Svcb sur le tas règle le cas, au prix de deux défauts : jemalloc arrondit à la classe de taille supérieure (un MX demande 40 octets et en occupe 48) et les données se dispersent, ce qui coûte des lignes de cache.

5. Garder les données au format wire. Plutôt qu'une liste de variantes analysées, un seul Box<[u8]> où chaque enregistrement est préfixé de sa longueur sur 2 octets. Les deux défauts précédents disparaissent, la lecture devient une copie directe pour A, AAAA, TXT et DNSSEC — seuls CNAME, NS, MX et SOA demandent encore une analyse, pour la compression de noms. Gain : 5 % de latence. L'écriture passe par un tampon de travail réutilisé puis un memcpy unique : 13 % d'insertions en plus à elle seule.

Stocker le message entier au format wire a été écarté : le drapeau DNSSEC OK obligerait à cacher deux variantes de chaque réponse.

Les résultats

Mesure Avant Après Écart
Empreinte par entrée 953 octets 420 octets −56 %
Allocations par entrée 1,1 Ko 461 octets −58 %
Débit d'insertion 625 000 /s 893 000 /s +43 %
Latence de lecture 828 ns 670 ns −19 %

En production, sur les instances Big Pineapple, la mémoire résidente p99 est passée de 9,3 à 5,3 Go entre le 18 mai et le 6 juillet 2026, date de fin du déploiement. Soit environ 100 To libérés — l'équivalent de la RAM de 130 serveurs Gen 13 — que Cloudflare compte réinvestir en capacité de cache plutôt qu'en économies.

Source : The Cloudflare Blog, Saving 100 terabytes of memory by optimizing 1.1.1.1's DNS cache