boost :: asio: поток локальных асинхронных событий - PullRequest
4 голосов
/ 24 февраля 2010

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

Я думаю: один socket привязан к адресу, совместно используемому несколькими io_service, где каждый поток получает свой io_service. Правильна ли эта линия рассуждений?

edit: похоже, мне придется самому ответить на этот вопрос.

Ответы [ 3 ]

5 голосов
/ 03 марта 2010

Да, ваши рассуждения в основном верны. Вы должны создать поток для каждого ядра, экземпляр io_service для каждого потока и вызвать io_service.run () в каждом потоке.

Однако вопрос в том, действительно ли вы так поступите. Вот проблемы, которые я вижу:

  • Вы можете получить очень занятые ядра и неработающие ядра в зависимости от того, как работа сбалансирована между вашими соединениями. Микрооптимизация для попаданий в кеш в ядре может означать, что вы потеряете возможность работать бездействующее ядро, когда «оптимальное» ядро ​​не готово.

  • На скоростях сокетов (т. Е. Медленных), сколько выигрыша вы получите от попаданий в кэш ЦП? Если для одного соединения требуется достаточно ресурсов ЦП, чтобы ядро ​​было занято, а количество подключений не превышало количество ядер, то это здорово. В противном случае неспособность переместить работу, чтобы справиться с дисперсией рабочей нагрузки, может уничтожить любой выигрыш, который вы получите от попаданий в кэш. И если вы выполняете много разной работы в каждом потоке, кеш все равно не станет таким горячим.

  • Если вы просто делаете ввод / вывод, выигрыш в кеше может быть не таким большим, независимо от того. Зависит от вашей фактической рабочей нагрузки.

Я рекомендую иметь один экземпляр io_service и вызывать io_service.run () в потоке на ядро. Если у вас недостаточная производительность или у вас есть классы соединений, в которых на одно соединение приходится много ресурсов ЦП, и вы можете получить выигрыши в кеше, переместите их в конкретные экземпляры io_service.

Это тот случай, когда вы должны выполнить профилирование, чтобы увидеть, сколько обходится вам с отсутствием кэша и где.

2 голосов
/ 24 февраля 2010

Если ваше серверное приложение должно работать на компьютере с Windows, вам следует рассмотреть возможность использования портов завершения ввода-вывода.

Может ограничивать количество активных потоков количеством ядер. Он распределяет события ввода-вывода из теоретически бесконечного числа сокетов в активные потоки. Планирование осуществляется ОС. Здесь хороший пример того, как это сделать.

0 голосов
/ 03 марта 2010

Можно использовать один io_service, который используется несколькими потоками, и strand, чтобы гарантировать, что соединение всегда обрабатывается одним и тем же потоком. Взгляните на пример HTTP-сервер 3 .

...