, поскольку это звучит так, как если бы вы использовали asio в качестве основного использования, это тот факт, что он построен поверх портов завершения ввода-вывода (для краткости iocp). Итак, начнем со сравнения iocp с WaitForMultipleObjects()
. Эти два подхода по сути такие же, как select
против epoll
в linux.
Основным недостатком WaitForMultipleObjects
, который был решен с помощью iocp, является невозможность масштабирования со многими дескрипторами файлов. Это O (n), поскольку для каждого полученного вами события вы снова передаете полный массив, и внутренне WaitForMultipleObjects должен сканировать массив, чтобы узнать, какие дескрипторы активировать.
Тем не менее, это редко проблема из-за второго недостатка. WaitForMultipleObjects()
имеет ограничение на максимальное количество дескрипторов, которые он может ожидать (MAXIMUM_WAIT_OBJECTS
). Это ограничение составляет 64 объекта (см. Winnt.h). Существуют способы обойти это ограничение, создавая объекты Event и привязывая несколько сокетов к каждому событию, а затем ожидая 64 события.
Третий недостаток состоит в том, что в WaitForMultipleObjects()
есть небольшая ошибка. Возвращает индекс дескриптора, который вызвал событие. Это означает, что он может передать только одно событие обратно пользователю. Это отличается от select
, который возвращает все файловые дескрипторы, которые вызвали событие. WaitForMultipleObjects
сканирует переданные ей дескрипторы и возвращает первый дескриптор, в котором было поднято событие.
Это означает, что, если вы ожидаете 10 очень активных сокетов, большинство из которых имеют события на них большую часть времени, будет очень сильный уклон в сторону обслуживания первого сокета в списке, переданном в WaitForMultipleObjects
, Это можно обойти, каждый раз, когда функция возвращается и событие обслуживается, запускайте его снова с таймаутом 0, но на этот раз только в той части массива 1, которая прошла после инициирующего события. Неоднократно, пока не будут посещены все маркеры, затем вернитесь к исходному вызову со всеми маркерами и фактическим таймаутом.
iocp решает все эти проблемы, а также представляет интерфейс для более общего уведомления о событии, что довольно неплохо.
С iocp (и, следовательно, asio):
- Вы не повторяете, какие дескрипторы вас интересуют, вы говорите Windows один раз, и он запоминает это. Это означает, что он намного лучше масштабируется с помощью множества ручек.
- У вас нет ограничения на количество дескрипторов, которые вы можете подождать
- Вы получаете каждое событие, то есть нет предвзятого отношения к какой-либо конкретной ручке
Я не уверен, что вы предполагаете использовать async_read
для пользовательского дескриптора. Возможно, вам придется проверить это. Если ваш дескриптор ссылается на сокет, я думаю, он будет работать.
Что касается вопроса о потоках; да. Если вы run()
io_service
в нескольких потоках, события отправляются в свободный поток и будут масштабироваться с большим количеством потоков. Это особенность iocp, которая даже имеет API пула потоков.
Вкратце: я полагаю, что asio или iocp обеспечат лучшую производительность, чем простое использование WaitForMultipleObjects
, но то, принесет ли вам эта производительность пользу, зависит в основном от того, сколько у вас ручек и насколько они активны.