Cloudflare радикально оптимизировал использование памяти своего DNS-сервиса 1.1.1.1, переработав структуру хранения данных лежащей в его основе платформы DNS-кэша под названием Big Pineapple. Как пишет компания в своем блоге (откроется в новом окне), платформа в любой момент времени хранит более 250 миллиардов записей DNS-кэша.
При таком высоком масштабировании потеря даже одного байта на запись приводит к дополнительной потребности в памяти более 250 гигабайт по всей серверной сети, пояснил провайдер. Чтобы снизить эту потребность, разработчики провели пять последовательных технических оптимизаций, которые сократили объем памяти на запись более чем вдвое.
Сначала динамические структуры данных, такие как Vec и String, были заменены на неизменяемые альтернативы, такие как Box<[T]> и Box<str>. Поскольку DNS-ответы, однажды помещенные в кэш, больше не нужно изменять, поле, ранее использовавшееся для будущей емкости, стало бесполезным. Этот шаг сэкономил 64 байта на запись и сократил неиспользуемую память в куче, что в сумме по всем записям должно сэкономить 15 терабайт.
Чистая потребность в памяти на запись кэша снижена на 56 процентов
Кроме того, отдельные списки для секций ответов, авторитетных записей и дополнительных записей были объединены в единый список, в котором секции адресуются с помощью компактных 2-байтовых смещений (u16), что сэкономило еще 28 байт на запись.
Третья оптимизация касалась доменного имени отдельных DNS-записей, которое по умолчанию полностью сохранялось в кэше для каждой записи. Поскольку в подавляющем большинстве случаев это имя совпадает с фактически запрошенным доменом, разработчики сделали это поле необязательным.
В-четвертых, они занялись размером памяти типа данных Enum в Rust. Enum в Rust по умолчанию всегда занимает в памяти столько места, сколько его самый большой вариант. Поскольку очень редко используемый вариант для NAPTR-записей занимал 136 байт, весь Enum записей, включая выравнивание, занимал 144 байта, хотя записи A и AAAA, составляющие более 80% трафика, требуют всего 4 и 16 байт соответственно.
Путем выноса более редких крупных вариантов за пределы структуры, встроенный размер для частых типов был уменьшен до 24 байт, что экономит 120 байт на каждую запись A и AAAA. Чтобы обойти недостатки выноса, на пятом шаге был выбран новый компромисс. Записи теперь хранятся в исходном формате передачи DNS (wire-format) в виде непрерывного массива байтов (Box<[u8]>).
В результате этих мер чистая потребность в памяти на запись кэша снизилась на 56% — с 953 до 420 байт, а количество выделений памяти сократилось на 58%. На практике это привело к постоянной экономии около 100 терабайт оперативной памяти по всему парку серверов. Cloudflare планирует использовать освободившуюся оперативную память для дальнейшего увеличения емкости кэша.