Cloudflare высвободила 100 ТБ оперативной памяти оптимизацией DNS-кэша

1000px.jpg

27 августа в Cloudflare рассказали о событии из разряда «однострочный патч с мультипликативным эффектом»: небольшая экономия памяти на одной структуре данных, будучи умноженной на сотни миллиардов экземпляров, превращается в десятки терабайт. Правда, в данном случае одним однострочным патчем дело не ограничилось — инженеры последовательно внесли пять сравнительно небольших изменений в представление записей DNS-кэша и в итоге высвободили около 100 ТБ оперативной памяти.

Оптимизации проводились в Big Pineapple — написанной преимущественно на Rust платформе Cloudflare, лежащей в основе публичного DNS-резолвера 1.1.1.1, Gateway DNS, DNS Firewall, AS112 и других DNS-сервисов компании. В каждый момент времени Big Pineapple хранит более 250 млрд записей DNS-кэша, поэтому всего один лишний байт на запись означает более 250 ГБ памяти на всей инфраструктуре.

Cloudflare начала развёртывание изменений 18 мая и завершила его 6 июля 2026 года. Оптимизация состояла из пяти основных этапов:

  • Вместо динамических Vec и String для неизменяемых после помещения в кэш данных стали использовать Box<[T]> и Box. У Vec кроме указателя и длины хранится ещё и ёмкость буфера, необходимая для его последующего расширения, но кэшированные DNS-ответы больше не изменяются. В каждой записи находилось восемь подобных полей, поэтому экономия только на этом изменении составила 64 байта на запись и более 15 ТБ в масштабах Cloudflare.

  • Три отдельных массива DNS-записей answer, authority и additional объединили в один массив, а границы секций стали задавать двумя 16-разрядными смещениями. Это позволило убрать два указателя и две длины и сэкономить ещё 28 байт на запись. Несколько логических полей заодно были упакованы в битовые флаги, что сократило и выравнивающие промежутки внутри структур Rust.

  • Из большинства записей перестали сохранять повторяющееся имя владельца DNS-записи. Обычно оно совпадает с доменом, уже присутствующим в ключе кэша. Теперь имя сохраняется отдельно только тогда, когда оно действительно отличается, например для записей за CNAME, а в остальных случаях восстанавливается из ключа.

  • Инженеры обратили внимание на особенности enum в Rust. Размер перечисления определяется его крупнейшим вариантом: в структуре Cloudflare таким вариантом был NAPTR, из-за которого RecordData занимал 144 байта. При этом наиболее распространённой записи A требуется всего 4 байта, а AAAA — 16 байт. Поскольку A и AAAA составляют более 80% обрабатываемых записей, большая часть выделенной памяти фактически оставалась пустой. Перенос крупных вариантов в отдельные heap-объекты позволил значительно уменьшить сам enum.

  • Наконец, от хранения разобранных Rust-структур для содержимого DNS-записей частично отказались вообще. Данные стали помещать в единый Box<[u8]> практически в сетевом формате DNS, добавляя перед каждой записью двухбайтовую длину. Это убрало множество отдельных выделений памяти и улучшило локальность данных для процессорного кэша. Для A, AAAA, TXT и DNSSEC-записей данные теперь можно непосредственно копировать в формируемый DNS-ответ, не выполняя повторную сериализацию. Само это изменение уменьшило задержку поиска примерно на 5%, а использование повторно применяемого временного буфера увеличило скорость добавления записей ещё на 13%.

В результате в тестах средний объём памяти на одну запись сократился с 953 до 420 байт, то есть на 56%, а фактически выделяемая память — с 1,1 КБ до 461 байта. На рабочих серверах эффект оказался несколько меньше, поскольку в RSS процесса входит не только DNS-кэш, но итоговая экономия по всей инфраструктуре всё равно составила примерно 100 ТБ оперативной памяти.

Экономия памяти при этом не потребовала жертвовать производительностью. Наоборот, пропускная способность при добавлении записей в кэш выросла с 625 тыс. до 893 тыс. записей в секунду, или на 43%, а задержка поиска снизилась с 828 до 670 нс, или на 19%. В production значение p99 для потребления памяти одним экземпляром Big Pineapple уменьшилось с 9,3 до 5,3 ГБ, а p90 — с 6,5 до 3,8 ГБ.

Высвободившиеся 100 ТБ Cloudflare сравнивает с объёмом памяти примерно 130 серверов поколения Gen 13. Однако вынимать DIMM из серверов компания, естественно, не собирается: свободную память планируется направить на увеличение DNS-кэшей. Более вместительный кэш повысит вероятность нахождения готового ответа и сократит число запросов к внешним авторитетным DNS-серверам.

Big Pineapple создавалась Cloudflare как собственная замена постепенно переросшей свои первоначальные задачи инфраструктуре на основе Knot Resolver. Компания ранее подробно рассказывала, что сервис со временем практически полностью переписали на Rust, а расширяемую часть архитектуры построили вокруг изолированных WebAssembly-модулей.

>>> Источник

©  Linux.org.ru