Fjord

За кулисами Fjord

Технологии, на которых работает Fjord.

Бот на Rust. Собственный графический движок. А также фреймворки, библиотеки и базы данных, на которых построен Fjord.

Здесь мы рассказываем о наших разработках и технологиях, из которых состоит Fjord.

01 БотFjord сохраняет порядок событий каждого сервера и обрабатывает независимые задачи параллельно.

Fjord

Обработка событий по порядку.

Fjord обрабатывает события Discord по порядку и выполняет независимые задачи параллельно. Twilight связывает бота с Discord и хранит данные серверов локально. Dragonfly хранит ожидающие события и помогает координировать соединения со шлюзом.

01

READY как граница состояния.

Новый READY ждёт завершения прежних задач до обновления состояния серверов. Следующие события запускаются позже, поэтому старая работа не перезапишет новое состояние.

02

FIFO для каждого сервера.

События одного сервера запускаются в порядке поступления. Каждое ждёт завершения предыдущего, чтобы изменения этого сервера не обгоняли друг друга.

03

Серверы работают параллельно.

Диспетчер различает задачи по ключам. Разные серверы могут работать одновременно; ждать друг друга должны только задачи с одним ключом.

04

Одно событие, нужные задачи.

Одно и то же сообщение одновременно поступает в AutoMod и журнал активности. Каждый обрабатывает его отдельно для своей задачи.

05

Временные данные в Dragonfly.

Ожидающие события Discord и их данные хранятся в Dragonfly. AutoMod и журналы активности также используют это общее хранилище для временного состояния. Выполнением задач по-прежнему управляет бот.

06

Одно совпадение, одна реакция.

Когда срабатывает активный фильтр AutoMod, проверка этого сообщения прекращается. Остальные фильтры не вызывают повторную меру для того же события.

07

Данные серверов в Twilight.

Twilight поддерживает в памяти актуальные данные серверов, участников, ролей, каналов, эмодзи, присутствия и голосовых состояний. Сообщения в этот кеш не входят.

08

Взаимодействия отдельно.

Взаимодействия планируются независимо от событий серверов. READY обозначает границу состояния внутри каждого соединения со шлюзом.

09

Ответственность за шарды.

Dragonfly координирует владение отдельными шардами — соединениями со шлюзом. После передачи прежний владелец не может брать в работу или завершать дальнейшие события.

02 Графический движок FjellОбработка изображений на Rust, SIMD и измеренная производительность.

01 / Собственная разработка

В наших изображениях узнаётся наш почерк.

Fjell — наш собственный графический движок на Rust. Он объединяет фоны, аватары и тексты в персональные приветственные карточки.

Мы хотели контролировать создание этих изображений. Поэтому разработали решение под задачи Fjord, которое даёт нам творческую свободу.

Не менее важна экономическая эффективность. Fjell обеспечивает максимальную производительность без потери качества и максимально эффективно использует процессор и оперативную память при генерации. Это значительно снижает наши расходы на серверы.

Наша реализация охватывает даже обработку пикселей. Собственные циклы SIMD используют AVX2, FMA и BMI1/BMI2 для параллельного вычисления нескольких пикселей.

Предпросмотр редактора Fjord с оформленной приветственной карточкой
Дизайн в Fjord. Рендеринг с Fjell.

Измерение производительности

Контролируемый тест*

Четыре уровня нагрузки, контролируемые варианты карточек и единая методика тестирования.

ПараллельноКарточек/сКарточек/минРендер ср.Рендер P50Рендер P95Рендер P99Всего ср.Всего P50Всего P95Всего P99CPU ср.RAM ср.
1797,4847.8491,062 ms1,061 ms1,226 ms1,242 ms1,253 ms1,251 ms1,428 ms1,473 ms88,3 %381,2 MiB
21.577,9594.6771,038 ms1,004 ms1,225 ms1,421 ms1,266 ms1,236 ms1,470 ms1,715 ms173,5 %360,1 MiB
43.173,00190.3801,023 ms1,011 ms1,188 ms1,230 ms1,259 ms1,243 ms1,448 ms1,557 ms344,9 %375,3 MiB
85.850,25351.0151,050 ms1,026 ms1,194 ms1,290 ms1,366 ms1,349 ms1,578 ms1,803 ms647,0 %385,8 MiB

Масштабирование пропускной способности

Измеренная пропускная способность в сравнении с идеальным линейным масштабированием.

ИзмереноИдеальная линейная
1248Параллельные воркерыКарточек/с
ВоркерыИзмереноИдеальная линейнаяМасштабированиеЭффективность
1797,48797,481,00×100,0 %
21.577,951.594,961,98×98,9 %
43.173,003.189,923,98×99,5 %
85.850,256.379,847,34×91,7 %

Все четыре локальных теста длились по 60 секунд на AMD Ryzen 9 9950X. Использовались 100 лёгких фонов с обычными цветами или иллюстрациями размером примерно от 100 до 300 КБ, обычно около 200 КБ. Жидкий слой был отключён, а шрифт оставался неизменным; между карточками менялись цвета и положения шейдеров текста и круга.

Время рендеринга включает создание изображения, кодирование и сжатие PNG до получения готового PNG. Передача по сети и время загрузки не включены.

Генератор нагрузки использовал 1, 2, 4 или 8 параллельных запросов. Новый запрос начинался только после полного получения и проверки предыдущего PNG. Указанная загрузка CPU возникла именно при такой нагрузке. Графический движок мог распределять работу между несколькими ядрами.

* Внутренние, независимо не проверенные измерения в описанных условиях. Они не являются гарантированной характеристикой, гарантией или обязательством по производительности. Фактическая производительность зависит от системы, нагрузки и среды.

Агрессивный случайный тест

Тест производительности со случайными карточками*

Значительно более вариативная схема с 1 000 фонов, 237 шрифтами и случайными эффектами в каждом запросе.

ПараллельноКарточек/сКарточек/минРендер ср.Рендер P50Рендер P95Рендер P99Всего ср.Всего P50Всего P95Всего P99CPU ср.RAM ср.
192,655.5599,775 ms10,478 ms12,781 ms13,401 ms10,788 ms11,553 ms14,006 ms14,784 ms93,6 %1.205,6 MiB
2184,5311.0729,944 ms10,621 ms12,858 ms13,550 ms10,832 ms11,576 ms13,938 ms14,698 ms189,1 %1.278,8 MiB
4358,8221.52910,209 ms10,855 ms13,240 ms13,997 ms11,138 ms11,857 ms14,363 ms15,212 ms377,7 %1.300,9 MiB
8660,5239.63110,897 ms11,610 ms14,343 ms15,336 ms12,101 ms12,889 ms15,838 ms16,880 ms744,8 %1.308,6 MiB

Масштабирование пропускной способности

Измеренная пропускная способность в сравнении с идеальным линейным масштабированием.

ИзмереноИдеальная линейная
1248Параллельные воркерыКарточек/с
ВоркерыИзмереноИдеальная линейнаяМасштабированиеЭффективность
192,6592,651,00×100,0 %
2184,53185,301,99×99,6 %
4358,82370,603,87×96,8 %
8660,52741,207,13×89,1 %

Эти четыре локальных теста длились по 60 секунд на том же AMD Ryzen 9 9950X. Каждый запрос выбирал один из 1 000 более сложных фонов размером от 800 КБ до 2,4 МБ и один из 237 шрифтов. Изменялись тексты, прозрачность, размеры шрифта и аватара, обводка, цвета текста и круга, а также угол, сила и интенсивность шейдеров. Примерно на половине карточек дополнительно включался жидкий слой со случайными цветом, непрозрачностью и размытием.

Генератор нагрузки использовал 1, 2, 4 или 8 параллельных воркеров в замкнутом цикле. Каждый воркер начинал следующий запрос только после полного получения и проверки предыдущего PNG. Все 60-секундные тесты завершились без ошибок, тайм-аутов и повреждённых PNG.

Время рендеринга включает создание изображения, кодирование и сжатие PNG до получения готового PNG. Передача по сети и время загрузки не включены.

* Внутренние, независимо не проверенные измерения в описанных условиях. Они не являются гарантированной характеристикой, гарантией или обязательством по производительности. Фактическая производительность зависит от системы, нагрузки и среды.

03 ТехнологииЯзыки, фреймворки, библиотеки, базы данных и объектное хранилище.

02 / Наша техническая основа

На чём мы разрабатываем.

Помимо собственного движка мы используем Rust, Leptos, TypeScript, Vue, Twilight, Dragonfly, PostgreSQL, ScyllaDB и RustFS. У каждой технологии своя понятная роль в системе.

Язык программирования

Rust

Rust

На Rust работают наш бот для Discord, серверная часть, редактор карточек и графический движок Fjell.

Логотип © Rust Foundation. CC BY 4.0 · без изменений

Веб-фреймворк

Leptos

Leptos

Leptos используется в отдельных частях нашего веб-интерфейса. Этот фреймворк позволяет использовать Rust в браузере и хорошо вписывается в остальной стек.

Логотип от сопровождающих Leptos. MIT · без изменений

Веб-фреймворк

Vue

Vue

Vue объединяет компоненты публичного сайта. К ним относятся навигация, документация и другие интерактивные области. Так интерфейс проще поддерживать и развивать.

Логотип © Evan You. CC BY-NC-SA 4.0 · без изменений

Библиотека для Discord

Twilight

Twilight

Для подключения к Discord мы используем Twilight. Эта библиотека связывает нашего бота на Rust с Discord.

Логотип от Fezhoof. CC BY-SA 4.0 · без изменений

База данных

Dragonfly — наше общее временное хранилище для событий Discord, координации шардов и нескольких соединений со шлюзом, AutoMod и журналов активности.

Программное обеспечение под BSL 1.1 с дополнительным правом использования.

Реляционная база данных

PostgreSQL дополняет наш слой данных там, где нужны реляционные данные и структуры. Он работает рядом со ScyllaDB как отдельная часть инфраструктуры.

Объектное хранилище

RustFS используется у нас как S3-совместимое объектное хранилище. Оно добавляет отдельный слой хранения рядом с PostgreSQL и ScyllaDB.

ПО по лицензии Apache 2.0. RustFS является товарным знаком RustFS, Inc.