Doom на DNS оказался не метафорой, а работающим экспериментом: после оптимизаций на обработку одного нажатия вправо уходит 54,4 секунды. Игра, конечно, не становится играбельной, зато опыт наглядно показывает неприятно универсальное свойство инфраструктуры: DNS с чтением записей и условной записью можно превратить в вычислительную машину. Для разработчиков это ещё один повод вспомнить, что «это же просто база данных» иногда звучит как начало очень странного технического проекта.
Автор эксперимента, инженер и колумнист Corey Quinn, собрал 32-битную машину, где арифметика и память вынесены в DNS-записи. Об этом сообщает The Register. Сам BIND не интерпретирует машинные инструкции и не изображает из себя процессор: декодирование сделано заранее компилятором, а DNS-сервер получает запросы на чтение ключей и условное обновление состояния. По сути, вычисления строятся на заранее подготовленных таблицах истинности и последовательности обращений к ним.
Внутри этой конструкции хранится около 6,4 млн записей с предрассчитанными ответами для базовых операций. Например, запись вида ff.01.0.add описывает результат сложения 255 и 1: нулевой младший байт и перенос единицы. Сервер имен здесь играет роль крайне усердного библиотекаря: не складывает числа сам, а выдаёт заранее сохранённый ответ на каждый допустимый вопрос. Из таких ответов собираются регистры, память, переходы и в конце концов кадры Doom.
Почему быстрый DNS не спасает медленную игру
На локальном BIND 9.20 один запрос обрабатывается примерно за 7 микросекунд по TCP и за 4 микросекунды по UDP. В нормальной жизни это достойные цифры. Но у виртуального компьютера на DNS 32-битное сложение требует четырёх DNS-запросов, условный переход — пяти, а формирование одного кадра — около 6,6 млн обращений. Поэтому разница между «быстрым ответом сервера» и «достаточной производительностью всей системы» становится почти комичной.
Первая попытка автора обработать нажатие клавиши вправо заняла 577 секунд. Затем он сократил результат до 146,3 секунды, а позже — до 54,4 секунды, то есть добился ускорения примерно в 10,6 раза. Для этого Quinn задействовал нативный транспорт, конвейеризацию запросов, плотнее упаковал регистры, стал реже фиксировать их состояние в DNS, перевёл часть обмена на UDP и настроил BIND так, чтобы тот не добавлял в ответы лишние authority-записи.
Однако дальше упираешься уже не в очевидные настройки. Даже в фантастическом сценарии, где на одну инструкцию требовался бы ровно один DNS-обмен, 1,4 млн инструкций при задержке около 10 микросекунд дали бы примерно 14 секунд на один тик. Doom рассчитан на 35 тиков в секунду — один должен занимать около 28,6 миллисекунды. В эксперименте речь идёт о 54 000 миллисекунд. До приемлемой реакции на клавиатуру остаются примерно три порядка величины, и никакой флаг конфигурации BIND тут не выглядит волшебной кнопкой.
DNS UPDATE как compare-and-swap
Самая интересная часть проекта — не возможность похвастаться очередным портом Doom, а использование RFC 2136 DNS UPDATE. Каждая фиксация состояния требует, чтобы предыдущее значение всё ещё совпадало с ожидаемым. Если оно уже изменилось, обновление не проходит. В терминологии баз данных это optimistic concurrency или compare-and-swap: безопасный способ обновить значение при конкурирующих операциях, не перетирая чужие изменения вслепую.
Quinn отдельно подчёркивает, что этот механизм существует в DNS с 1997 года. На эксперимент отреагировал Paul Vixie — один из пионеров DNS и архитектор BIND 8, а также соавтор RFC 2136. По словам автора, Vixie назвал работу лучшим применением DNS UPDATE, которое ему доводилось видеть. Комплимент заслуженный, хотя для тех, кому потом поддерживать корпоративные зоны, вряд ли успокаивающий.
Корректность работы проверяется независимо: каждый пиксель сформированного кадра сверяют с отдельным эмулятором. Если повредить хотя бы одну запись в таблице операции AND, результат кадра изменится — это должно исключить скрытую локальную арифметику. Автор также подготовил инструменты, позволяющие воспроизвести проверку двумя командами. Для замера использовалась не полная загрузка игры: стартовое состояние было подготовлено обычным эмулятором, поскольку прохождение стартовых экранов Doom через DNS заняло бы часы. Ещё около минуты требуется на загрузку миллионов записей до начала работы.
Doom на DNS запущен на Debian со штатным BIND 9.20, настроенным через named.conf, внутри контейнера без сетевого доступа. Практической пользы у такого компьютера, разумеется, нет: его нельзя рекомендовать ни для игр, ни для расчётов, ни тем более для замены СУБД. Но эксперимент хорошо отделяет привычные ярлыки от возможностей системы. DNS — не CPU, однако сочетание адресуемого хранения, чтения, условной записи и огромной таблицы заранее вычисленных ответов уже достаточно для универсальных вычислений.
Для инженеров вывод здесь не «давайте запускать сервисы на DNS», а более полезный: ограничения платформы часто находятся не там, где их ожидают. Семантика операции может оказаться сильнее её обычного назначения, а производительность — беспощадно напомнить о цене каждого сетевого раунда. Исходный код и средства проверки эксперимента автор опубликовал вместе с разбором на . Следующий логичный вопрос для инфраструктурных команд звучит не «можно ли вычислять на DNS», а «какие ещё привычные сервисы уже обладают неожиданной вычислительной семантикой — и не используем ли мы её случайно в проде».