Интересные решения с HighLoad Cup

Не так давно прошёл чемпионат для backend-разработчиков highload Cup от Mail.Ru Group, который я к сожалению пропустил. Однако, это не мешает оценить решения других участников и сделать выводы. Суть конкурса проста: используя любой стек технологий написать как можно более производительное приложение под ограниченные серверные ресурсы обрабатывающее заранее определённый набор запросов и упаковать его в docker контейнер. Естественно, в лидерах оказались решения на C/C++, Java, GoLang. Что удивительно, PHP стек оказался производительнее NodeJS и Python решений.

Условия конкурса можно разделить на 2 задачи: быстрый веб-сервер и высокопроизводительное хранилище данных, желательно в оперативке. Будет очень хорошо, если вы предварительно ознакомитесь с условиями конкурса и вариантами решения, в данном обзоре я их не упоминаю.

Одним из наиболее интересных трюков мне показалось решение хранить базу данных в оперативке в бинарно-упакованном виде, читать байты по нужному смещению и декодировать. Скорость чтения и декодирования одной записи из такого справочника без нагрузки варьируется от 0.000002 до 0.000012 секунды. Для сравнения, скорость чтения и декодирования из APCu (apcu_add + apcu_fetch) находится в пределах 0.000002 — 0.000004, однако, не гарантирует хранения данных т.к. является кэшем. А Memcached по TCP выдаёт вообще 0.000012 — 0.000037. Скорость работы подобного решения под нагрузкой — тема для отдельной статьи.

Данный способ хранения отлично подходит для массива данных с записями фиксированной длины и подряд идущими идентификаторами, иначе эффективность такой структуры будет падать. Главный профит подобного хранения — отсутствие оверхедов структур данных на хранения мета-информации, например ключей, а так же огромный оверхед на zval. Хранение оригинального справочника визитов в PHP-массивах занимало бы в памяти от 2790 Мб до 5510 Мб, в зависимости от формата, а оптимизации с помощью SplFixedArray снижают потребление до 704 Мб. Бинарный же вариант хранения потребляет всего 116 Мб.