目の前に隠れていた100テラバイトの問題
「Big Pineapple」という名のプラットフォームで運用されるCloudflareのグローバルDNSインフラは、驚異的な規模で稼働しています。1.1.1.1、Gateway DNS、DNS Firewallといった世界中の無数のユーザーを支える重要なサービスを支え、2500億以上のDNSキャッシュエントリを常に管理しています。
この巨大な運用フットプリントにもかかわらず、Cloudflareのエンジニアは、蔓延する隠れた非効率性を発見しました。953バイトとベンチマークされた一般的なDNSキャッシュエントリには、DNSデータそのものではなく、内部データ構造の管理に費やされるかなりの割合の「メモリオーバーヘッド」が含まれていました。例えば、RustのデフォルトのVec型やString型は、ポインタ、長さ、容量フィールドを格納します。
成長することのない静的なキャッシュ済みDNSレコードにとって、この容量フィールドは不要な負担となり、貴重なメモリを消費していました。この一見些細な非効率性は、広大なネットワーク全体で劇的に増幅されました。2500億のレコードに対して1エントリあたりわずか1バイトの無駄であっても、250ギガバイト以上の余分なRAMを消費することになります。
この広範なメモリの無駄は、サーバー全体の運用コストに匹敵し、データ構造設計における小さな見落としが、いかに膨大なインフラ費用へと膨れ上がるかを浮き彫りにしました。Cloudflareの発見は、Rustのような高レベル言語であっても、きめ細かなメモリ管理がいかに重要であるかを強調しました。
容量の排除:Rustの諸刃の剣
Rustのデータ構造は、柔軟性を優先することがよくあります。VecやStringのような標準型は、将来の成長のために余分な「容量」を確保し、必要以上にメモリを割り当てることで動的データを効率的に管理します。各インスタンスは、データへのポインタ、現在の長さ、そしてこの事前割り当てされた容量という3つの情報を暗黙的に格納します。
この戦略は可変データには非常に効果的ですが、不変レコードにとっては純粋な無駄となります。Cloudflareの2500億のDNSキャッシュエントリは、一度保存されると固定され、拡大も縮小もしません。したがって、追加の容量フィールドは「Big Pineapple」内では何ら機能的な目的を果たさず、貴重なシステムリソースを消費していました。
この非効率性を認識したエンジニアは、VecやStringを「boxed slices」(Box<[T]>)や「boxed strings」(Box<str>)に置き換えました。これらの特殊なRust型は、データに必要な正確なメモリのみを割り当て、容量フィールドを完全に排除します。この一見小さな変更により、個々のキャッシュエントリあたり64バイトの節約が実現しました。
Cloudflareの広大なグローバル艦隊全体で、この最適化により15TB以上のRAMが即座に解放されました。これは、データ構造のセマンティクスに対する深い理解と、アプリケーションの特定の要件を組み合わせることで、いかに巨大な効率向上を実現し、休眠状態のメモリをアクティブで利用可能なリソースに変えることができるかを示しています。
ボックスを超えて:データパッキングの技術
Cloudflareは、回答(answer)、権威(authority)、追加(additional)といったDNSセクションの個別のポインタを超え、「密にパッキングされた(tightly packed)」データ戦略を採用しました。彼らはこれらのセクションを単一の連続したメモリブロックに統合し、2バイトの小さなオフセットを使用して各パーツへ正確に移動するようにしました。これによりポインタのオーバーヘッドが排除され、キャッシュエントリサイズが953バイトから1エントリあたりわずか420バイトへと56%削減されることに大きく貢献しました。
さらなる最適化として、キャッシュ内の冗長性と構造的な非効率性に対処しました。Cloudflareは、クエリと重複する所有者名を保存するのをやめ、必要な場合にのみキャッシュキーから再構築するようにしました。Rustのenumサイズはデフォルトで最大のバリアントに合わせられるため、NAPTRのような大きく稀なレコード型に対してboxingを実装しました。これにより、AやAAAAのような小さく一般的なレコードが占有するメモリを大幅に削減できました。
最後の大きな変更は、完全に解析されたRustの構造体ではなく、生の長さプレフィックス付きのwire-format bytesとしてレコードデータを保存することです。これにより、常に解析する必要のないデータに対してRustの豊富な型システムによるメモリオーバーヘッドを回避し、Big Pineappleの2500億件のキャッシュエントリ全体のメモリフットプリントをさらに縮小しました。これらの独創的なメモリ節約技術の詳細については、How we saved 100 terabytes of memory by optimizing 1.1.1.1's DNS cache | Cloudflare Blogをご覧ください。
この記事が気に入ったら、毎朝同じようなものをメールで受け取れます。
1日1通 · 2クリックで解除 · サードパーティのトラッキングなし
成果:より高速に、そしてより軽量に
綿密なデータ再設計により、驚くべき成果が得られました。Cloudflareは、DNSキャッシュエントリの平均サイズを953バイトからわずか420バイトに削減しました。これは、エントリあたりのメモリフットプリントが56%削減されたことを意味します。2500億件以上のキャッシュエントリを管理するCloudflareのグローバルなインフラ全体で、この最適化により、新しいサーバーを1台も追加することなく、合計100テラバイトものメモリを解放しました。
重要なのは、これらのメモリ節約がパフォーマンスの低下を招かなかっただけでなく、逆に操作が大幅に高速化したことです。キャッシュへの挿入は43%高速化し、1秒あたり625,000件から893,000件へと飛躍的に向上しました。同様に、ルックアップも19%の速度向上が見られ、レイテンシは828ナノ秒から670ナノ秒へと短縮されました。この稀な「両得」のシナリオは、リソース効率の大幅な向上と運用速度の強化を同時に実現し、従来のトレードオフを覆すものとなりました。
Cloudflareは、解放された100テラバイトのメモリを戦略的に活用し、DNSキャッシュ容量を拡大します。より大きく堅牢なキャッシュにより、「Big Pineapple」プラットフォームはより多くのクエリをローカルで解決できるようになります。これは、アップストリームサーバーからデータを取得する必要性を直接的に減らし、世界中のユーザーにとってDNS解決の高速化につながり、結果として誰にとってもインターネット速度が目に見えて向上します。
よくある質問
Cloudflareはこの最適化でどれくらいのメモリを節約しましたか?
Cloudflareは、グローバルなインフラ全体で約100テラバイト(TB)のRAMを解放しました。これは、新しいハードウェアを追加することなく、約130台のサーバーのメモリに相当します。
メモリの最適化によってCloudflareのDNSは遅くなりましたか?
いいえ、最適化は逆の効果をもたらしました。キャッシュへの挿入は43%高速化し、ルックアップは19%高速化しました。これにより、メモリ使用量と速度の間の一般的なトレードオフという通説が否定されました。
Cloudflareはこれを実現するためにどのプログラミング言語を使用しましたか?
CloudflareはRustプログラミング言語を使用しました。Rustのきめ細かなメモリ制御機能を活用し、DNSキャッシュエントリの構造を書き換えました。
Cloudflareが行ったメモリ節約のための主な変更は何ですか?
重要な変更は、VecやStringといった標準的なRustのデータ型をBox<[T]>やBox<str>に置き換えたことです。これにより、サイズが変化しないキャッシュデータに対して不要だった「容量(capacity)」フィールドが排除され、エントリあたり64バイトの節約になりました。
CloudflareはどのようにしてDNSキャッシュエントリのサイズを56%削減しましたか?
彼らは5つの主要なRustレベルの変更を実装しました。容量フィールドの排除、データセクションのオフセット付き単一ブロックへのパッキング、冗長情報の削除、大きなenumバリアントのboxing、そしてデータを生のwire formatで保存することです。

