производительность boost::interprocess message_queue - довольно медленная?

Мне нужен сверхбыстрый механизм MQ, где и отправитель, и получатель написаны на C++ на платформе Windows.

Моя текущая реализация с использованием RCF-C++ для IPC работает со скоростью около 20 000 msg/sec. через именованные каналы Windows.

Я тестирую производительность очередей сообщений boost::interprocess в соответствии с демонстрационное приложение, и я измеряю около 48 000 сообщений в секунду, что на удивление медленно, учитывая, что, когда я приготовил простую связь с отображенным в память файлом на той же машине (на C#, используя код из этого сообщения в блоге), я получил около 150 000 сообщений в секунду.

Любая идея о том, почему у меня такая низкая производительность из boost message_queue, и что я могу попытаться улучшить?


person Omer Raviv    schedule 02.06.2011    source источник


Ответы (2)


Ответ Дэниела является частью этого, но здесь есть более серьезная проблема: boost::interprocess в основном поддерживает очередь как массив в общей памяти, а при отправке сообщения boost::interprocess:message_queue выполняет двоичный поиск на основе приоритет нового сообщения, чтобы найти, где сообщение должно быть помещено в массив, а затем std::backward_copys все остальные сообщения, чтобы освободить место для него. Если вы всегда используете один и тот же приоритет, ваше сообщение будет помещено в начало (поскольку оно самое новое), и поэтому любые сообщения, которые у вас есть в буфере в это время, будут скопированы назад, чтобы освободить для них место, что требует времени. (См. реализацию метода queue_free_msg).

Если вам не нужны сообщения с приоритетами, а нужна обычная очередь FIFO, то этот подход намного медленнее, чем использование Circular. Буфер: производительность вставки (отправки) быстро ухудшается по мере роста размера очереди.

ОБНОВЛЕНИЕ: с помощью примечаний в Википедии я написал версию message_queue, в которой используется циклический буфер., и это имело большой успех.

person Omer Raviv    schedule 22.06.2011
comment
Омер, вы могли бы отправить свою версию message_queue, которая использует кольцевой буфер, самому Boost. Они могут принять это! - person Pietro; 10.08.2011
comment
@Pietro Слишком ленив, чтобы это делать, но вы можете увидеть код по адресу gist.github.com/3171076. Этот код нужно подчистить — убрать все упоминания о приоритете сообщения, новая реализация его полностью игнорирует. - person Omer Raviv; 24.07.2012
comment
Я знаю, что это довольно старая версия, но я проверяю, чтобы использовать message_queue в boost, и я обнаружил, что она сейчас в Boost (начиная с 1.52: boost.org/users/history/version_1_52_0.html, см. BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX ) - person MGamsby; 09.05.2018

Как указано в документе Boost , boost::interprocess::shared_memory_object реализован с использованием файла отображения памяти в Win32. И очередь сообщений boost также использует этот смоделированный объект общей памяти. (Для встроенной общей памяти Win32 boost предоставляет класс windows_shared_memory отдельно.)

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

Обратите внимание, что если вы переходите на собственную общую память Win32, вы должны позаботиться об «удалении» общей памяти. Общая память POSIX и общая память Win32 имеют разную политику удаления.

person Daniel K.    schedule 02.06.2011
comment
Спасибо! Дох. Теперь я заметил, что действительно во время моих тестов в файловой системе был создан файл, который использовался для «симуляции» общей памяти. Есть ли шанс, что вы могли бы поделиться своей реализацией или узнать другую среду C++ MQ/RPC, основанную непосредственно на родной общей памяти Windows? Мне трудно поверить, что где-то нет готового решения? - person Omer Raviv; 02.06.2011
comment
Я попытался изменить boost message_queue для использования windows_shared_memory, как вы предложили, со следующими изменениями в message_queue.hpp, которые я нашел в Google: (1) заменить detail::managed_open_or_create_impl‹ windows_shared_memory, false › m_shmem; с подробностями::managed_open_or_create_impl‹shared_memory_object› m_shmem; (2) изменить заголовок, включив в него windows_shared_memory.hpp вместо shared_memory_object.hpp (3) закомментировать message_queue::remove, чтобы он просто возвращал true; Теперь я не вижу, чтобы он создавал файл в файловой системе, но производительность точно такая же. Есть идеи? - person Omer Raviv; 02.06.2011
comment
Я думаю, что ваша реализация почти такая же, как моя. Но производительность может зависеть от многих факторов, таких как длина сообщений. Среди прочего, в моем тесте открытие очереди сообщений было намного быстрее при использовании общей памяти Win32. - person Daniel K.; 07.06.2011
comment
Комментарий Даниэля в точку. Оба в конечном итоге используют файлы, отображаемые в память, но windows_shared_memory использует файлы, хранящиеся в системном файле подкачки, а не временные обычные файлы, используемые объектом shared_memory_object. Это позволяет windows_shared_memory пропустить фактическое создание файла на диске (я полагаю, если ОС не выгружает вашу память), что может иметь огромное значение, если вы отправляете очень большие сообщения; в противном случае простое размещение файла на диске может занять секунды/минуты, даже если последующие операции чтения/записи выполняются так же быстро, как и windows_shared_memory - person aggieNick02; 25.04.2019
comment
В Boost есть даже открытый билет 7-летней давности, чтобы добавить поддержку windows_shared_memory в очередь сообщений, но, похоже, он так и не получил поддержки: svn.boost.org/trac10/ticket/7027 - person aggieNick02; 25.04.2019