Перейти к основному содержимому
Нормативная версия документации - английская

Эта страница переведена с английского языковой моделью. При любом расхождении верен английский оригинал.

Методология

Как ruststream-amqp измеряет себя: три цикла, прогон на настоящем брокере, арифметика «упирается в брокер» и подсчёт кода. Процедура общая для всего фреймворка (методология RustStream), а эта страница говорит, как она выглядит на AMQP 1.0.

Три цикла​

Один процесс прогоняет сценарий трижды, тремя циклами, которые различаются одним: тем, что доставляет сообщения.

  • Сырой клиент. Получатель fe2o3-amqp, с которым цикл работает напрямую: принять, декодировать, прочитать поле, ответить accepted.
  • Крейт брокера. Этот крейт и ничего над ним: брокер подключается, дескриптор адреса открывает подписку, а цикл забирает доставки из её потока, декодирует их и подтверждает.
  • RustStream. Сервис, который пишет пользователь: обработчик #[subscriber] и приложение вокруг него.

Всё остальное в трёх циклах одинаково: соединение, сеанс каждой связи, кредит связи 256, гарантия доставки, место ack, декодирование в ту же структуру, байты полезной нагрузки, рантайм tokio с четырьмя рабочими потоками и бинарник.

Тело сообщения - 512 байт JSON. Оно декодируется в структуру из двух целочисленных полей, поэтому декодирование ничего не выделяет, и число говорит об этом крейте, а не о парсере JSON.

Прогон​

  • Новый адрес на каждый прогон. Прогон никогда не видит того, что оставил предыдущий.
  • Потребитель присоединяется первым. Затем ему отправляет сообщения издатель на втором соединении и опережает его не больше чем на 8192 сообщения. Издатель отправляет их уже урегулированными, поэтому прогон измеряет сторону приёма, а не то, как быстро брокер подтверждает отправку.
  • Окно открывается на первой доставке и закрывается, когда декодирована последняя, во всех трёх циклах. Подключение, открытие сеансов и присоединение связей в него не входят.
  • Число сообщений даёт пробный замер скорости сырого цикла, поэтому измеряемый прогон на любой машине длится не меньше пяти секунд.
  • Циклы чередуются: сырой, крейт, RustStream, три круга. Каждый цикл сообщает свой лучший, медианный и худший круг.

Строка получает пометку «упирается в брокер», когда потребитель большую часть прогона ждал брокер. Это арифметика. Пробный замер засекает 20000 отправок, каждая из которых ждёт своей диспозиции, и берёт медиану. Транспорт сообщает, сколько круговых обменов стоит одна доставка, и строка получает пометку, когда их произведение достигает половины измеренного времени на сообщение. Здесь доставка не стоит ни одного кругового обмена: брокер отправляет передачи в счёт кредита, который клиент пополняет в фоне, а accepted отправляется без ожидания ответа. Круговая задержка публикуется вместе с машиной, так что арифметику можно проверить.

Подсчёт кода​

Каждый сценарий графика стоимости - сервис, который пишет пользователь, на AmqpBroker против того же брокера, собранный без фичи testing, на однопоточном рантайме. Отдельный поток на другом соединении заполняет очередь между измеряемыми областями, и каждая его публикация ждёт, пока брокер её примет.

Инструкции даёт callgrind, выделения памяти - DHAT. Сценарий прогоняется на одной доставке, затем на 1000, затем на 2000. Разность двух последних - установившаяся стоимость сообщения, а одна доставка - холодный старт.

Сокет настоящий, поэтому счёт немного меняется между прогонами одного бинарника: сколько передач приносит одно чтение, зависит от того, что брокер успел записать к этому моменту. Прогон против сохранённого базового замера не проходит, если сценарий тратит на два процента больше инструкций. Выделения памяти на каждом прогоне сверяются с порогом, который объявляет каждый сценарий: наибольший замеченный итог плюс десятая доля процента.

Как запустить самому​

just bench

Рецепт поднимает стенд из docker-compose.test.yml, прогоняет сравнение, останавливает стенд и перезаписывает docs/benchmarks/results.json. Это занимает около минуты, и машина на это время нужна целиком. Рецепт очищает RUSTFLAGS, поэтому бинарник не привязан к процессору, на котором его собрали. Оба рецепта собирают бенчмарки так же, как собирается выпуск: с полной оптимизацией при компоновке через границы крейтов. Поэтому числа описывают тот код, который получает сервис.

just bench-code

Подсчёт кода занимает около половины минуты и требует valgrind. Рецепт сам устанавливает инструмент запуска бенчмарков той версии, которую закрепляет lock-файл. just bench-code --save-baseline=main на main записывает базовый замер, а just bench-code --baseline=main на ветке сравнивает с ним.