Ускорить внедрение ASIO IO_SERVICE?

Я писал инфраструктуру асинхронного ведения журналов, в которой у меня было несколько потоков, выгружающих данные. Я начал играть с Boost asio, потому что он предлагал несколько простых способов принудительной сериализации и упорядочения. Поскольку я новичок, я начал свой проект с потокобезопасного (использовал boost::mutexи boost:condition_variable) кругового bounded_buffer (который на самом деле был векторным).

Я написал небольшой простой тест для измерения производительности. Эталонный тест — это всего лишь один поток, регистрирующий миллион сообщений (помещая его в буфер), и мой рабочий поток просто собирал сообщения из очереди для регистрации в файле/консоли/списке регистраторов. (P.S. Использование мьютекса и CV было правильным, а указатели на сообщения перемещались, так что с этой точки зрения все было хорошо/эффективно).

Когда я изменил свою реализацию на использование boost::asio::io_serviceи наличие одного потока, выполняющего run(), производительность действительно улучшилась (на самом деле она очень хорошо масштабировалась). на увеличении количества регистрируемых сообщений, а не на снижении производительности в моей первоначальной простой модели)

Вот несколько вопросов, которые я хочу прояснить.

  1. Зачем повышать производительность? (Я думал, что внутренняя реализация boost::asio::io_serviceимеет потокобезопасную очередь для обработчиков, что делает ее намного более эффективной, чем мой собственный первоначальный простой проект потокобезопасной очереди). Пожалуйста, обратите внимание, что мой проект был хорошо проверен и не имел ошибок как таковых (скелет кода был основан на проверенных примерах), может ли кто-нибудь пролить больше света на внутренние детали того, как io_serviceэто реализует.

  2. Второе интересное наблюдение заключалось в том, что при увеличении количества потоков моя первоначальная производительность реализации улучшалась, но за счет потери сериализации/упорядочения, но производительность снижалась (очень незначительно) с boost::asio (я думаю, это потому, что мои обработчики выполняли очень упрощенная задача, и накладные расходы на переключение контекста ухудшались, я попытаюсь поставить более сложную задачу и опубликую свои наблюдения позже).

  3. Я действительно хотел бы знать, предназначен ли boost::asioтолько для операций ввода-вывода и сетевых операций, или мое использование его для выполнения параллельных задач (параллельных) через пул потоков является хороший дизайнерский подход. Является ли объект io_serviceпросто предназначенным для использования для объектов ввода-вывода (как написано в документации), но я нашел его действительно интересным способом помочь мне решить параллельные задачи (не только связанные с вводом-выводом или сетью) сериализованным способом (иногда с принудительным порядком с использованием цепочек). Я новичок в повышении, и мне действительно любопытно, почему базовая модель не работает/масштабируется так же хорошо, как когда я использовал boost asio.

Результаты: (в обоих случаях у меня был только 1 рабочий поток)

  • 1000 задач: 10 мкс/задача в обоих случаях
  • 10000 задач: 80 мкс (ограниченный буфер), 10 мкс в boost asio
  • 100000 задач: 250 мкс (граничный буфер), 10 мкс в boost asio

Было бы интересно узнать, как boost решает проблему потокобезопасности в io_serviceпотокобезопасной очереди для обработчиков (я всегда думал, что на каком-то уровне реализации они также должны использовать блокировки и cv ).

8
задан Sam Miller 20 March 2012 в 16:12
поделиться