Движок wb-rules: сократить аллокации при сопоставлении точных MQTT-подписок

Коллеги!

Автор запроса ChatGPT 6 Astra Work Mode :slight_smile: но я присоединяюсь и полностью поддерживаю. Запрос возник из оптимизации работы большого проекта на wb-rules.


Просим оптимизировать сопоставление MQTT-топиков в клиенте, включённом в штатный wbgo.so.

На физическом контроллере с wb-rules 2.40.0-wb100 у драйверного клиента зарегистрировано 2 487 подписок. В двух профилях на маршрутизацию/сопоставление MQTT приходилось 51,6% и 54,1% сэмплированного CPU. В Paho Go v1.5.0 несовпадающая точная подписка всё равно проходит разбиение строк и универсальное сопоставление.

Предлагаем:

  1. Сохранить немедленный успех при полном равенстве фильтра и топика.
  2. При неравенстве, если фильтр не содержит + или # и не относится к существующей обработке shared subscriptions, немедленно возвращать несовпадение без разбиения строк.
  3. Для wildcard/shared subscriptions сохранить прежний алгоритм. Не менять порядок обработчиков, регистрацию/удаление подписок, QoS и reconnect. Индекс или кэш не нужен.

Результат отдельного прототипа на 2 486 точных подписках и одном wildcard-фильтре:

  • Аллокации на сообщение: 4 974 → 2.
  • Сопоставление на ARM64 под QEMU: 5,623 → 0,610 мс.

Это стендовый тест алгоритма, а не измеренное ускорение физического WB. Проверены точные/wildcard/shared фильтры, порядок и замена/удаление обработчиков. Прошли 24 интеграционных теста с Go 1.21.4 -race и Mosquitto 2.0.20, включая QoS 0–2, сессии и reconnect.

Просим включить эквивалентную оптимизацию в официальную сборку и сравнить аллокации, CPU маршрутизации и задержку команды при одинаковых подписках и входящем потоке. Патч, тесты и профили сохранены и доступны для проверки.

Коллеги, добрый день!

А правильно ли я понял, что вам надо: чтобы MQTT-клиент в wb-rules при большом числе подписок (у вас 2 487) не тратил лишнюю работу на проверку «подходит ли топик к подписке», когда в подписке нет + и #? То есть просто сравнивал две строки, и если они не равны, сразу считал, что не подходит. Для подписок с +, # и shared всё должно работать как раньше.

Добрый день! Да, вы правильно поняли предложение.

Для обычной подписки без + и # достаточно сравнить полный топик сообщения с полной строкой подписки. Если строки не равны, сразу признать, что сообщение не соответствует этой подписке, без разбиения строк на части. При полном равенстве сохранить немедленное подтверждение совпадения.

Подписки с + и #, а также подписки вида $share/… должны обрабатываться как прежде. Порядок вызова обработчиков и остальное поведение клиента менять не предлагаем.

Добрый день! Ваше пожелание передано разработчикам.

Александр, спасибо за ответ и за передачу пожелания разработчикам!