| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > boost::asio::io_service.run() и много блокировок |
| Автор: phprus 17.11.2012, 16:56 | ||
| Доброго времени суток! Написал я некоторый сервер с использованием boost.asio по модели, когда есть один экземпляр io_service и пул потоков по числу cpu, каждый из которых выполняет run(). Профилирование сервера показало просто дикое число блокировок мутексов и условных переменных внутри ASIO при использовании epoll. Сейчас на маленьких тестах это миллионы блокировок, на больших тестах и при нормальной работе будут миллиарды, что душу явно не греет и не факт, что способствует использованию всех 4-х ядер существующей железки и всех 20 планируемой. Почитав документацию я увидел следующее http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/overview/implementation.html :
и похоже именно отсюда растут уши такого количества блокировок. Подскажите пожалуйста, как с осознанием всего этого жить и есть ли выходы, лучшие чем переписывание на модель вида пул потоков в каждом из которых свой io_service и жестким распихиванием клиентов по этим io_service при подключении или еще какую-нибудь модель? |
| Автор: mabrarov 17.11.2012, 18:30 |
| Вот http://asio-samples.blogspot.ru/2012/07/asio-performance-test.html, http://www.blogger.com/comment.g?blogID=3767932718256497924&postID=8263472374514844 и https://github.com/virtan/mrps есть некоторые размышления http://comments.gmane.org/gmane.comp.lib.boost.asio.user/5326. Вкратце, вы правы - придется применять "модель вида пул потоков в каждом из которых свой io_service и жестким распихиванием клиентов по этим io_service при подключении". Этот выбор можно и отложить на run time - см. проект echo_server (qt_echo_server) из https://asio-samples.svn.sourceforge.net/svnroot/asio-samples/trunk. Если же углубиться в детали, то "виновата" не библиотека Boost.Asio а сам epoll (точнее его реактивная идеология). В Windows, с его проактором на уровне ОС, я не смог повторить эту проблему. |
| Автор: mabrarov 19.11.2012, 00:22 | ||
Модель (одну из)
|
| Автор: phprus 24.11.2012, 15:36 |
Да, действительно. В итоге я остановился на следующей структуре приложения: 1) main_io_service - не занимается вообще ничем кроме как отслеживания сигналов операционной системы (SIGINT и т.д.), выполняется в главном потоке отвечает за управление модулями, корректное завершения приложения и т.д. 2) background_io_service и пул потоков, выполняющих background_io_service.run() - предназначен для выполнения тяжелых фоновых операций. Вспомогательные таймеры, загрузка/выгрузка на диск различных данных, с которыми можно оперировать в фоновом режиме. 3) пул потоков, в каждом свой io_service - для обслуживания сетевой активности. Сокет в момент создания прикрепляется к одному из потоков. Так как большинство моих действий при работе с сетью очень легкие, то это работает нормально даже не смотря на наличие некоторого количества mutex'ов для защиты общих структур данных. Вначале я беспокоился, что один глобальный mutex будет тормозить, но тестирование показало что до момента, когда я упрусь в него еще очень и очень долго (глобальный mutex защищает map объектов, которые нужно доставать по ключу, а так как map редко, но все-же меняется, то пришлось использовать mutex). |
| Автор: borisbn 24.11.2012, 16:07 | ||||
посмотри http://www.boost.org/doc/libs/1_51_0/doc/html/thread/synchronization.html#thread.synchronization.mutex_types.shared_mutex
ИМХО как раз твой случай |
| Автор: phprus 25.11.2012, 10:01 |
| borisbn, Спасибо за совет про Boost.shared_mutex, я про него правда знаю. В ближайшее время посмотрю на сколько shared_mutex будет лучше. |