В документации Windows IOCP рекомендуется использовать не более одного потока на доступное ядро на порт завершения. Гиперпоточность удваивает количество ядер. Поскольку использование IOCP приводит к созданию для всех практических целей приложения, управляемого событиями, использование пулов потоков добавляет в планировщик ненужную обработку.
Если вы задумаетесь, то поймете, почему: событие должно быть обслужено полностью (или помещено в какую-то очередь после начальной обработки) как можно быстрее. Предположим, что пять событий поставлены в очередь на IOCP на 4-ядерном компьютере. Если с IOCP связано восемь потоков, вы рискуете, что планировщик прервет одно событие, чтобы начать обслуживание другого, используя другой поток, который неэффективен. Это также может быть опасно, если прерванный поток находился внутри критической секции. С четырьмя потоками вы можете обрабатывать четыре события одновременно, и как только одно событие будет завершено, вы можете начать с последнего оставшегося события в очереди IOCP.
Конечно, у вас могут быть пулы потоков для обработки, не связанной с IOCP.
ИЗМЕНИТЬ __ _ __ _ __ _ __ _ __ _ _
Сокет (файловые дескрипторы тоже работают нормально) связан с IOCP. Процедура завершения ожидает IOCP. Как только запрошенное чтение из сокета или запись в сокет завершает работу ОС - через IOCP - освобождает процедуру завершения, ожидающую IOCP, и возвращается с дополнительной информацией, которую вы предоставили, когда вы вызывали чтение или запись (я обычно передаю указатель на блок управления). Таким образом, процедура завершения немедленно «знает», где найти информацию, относящуюся к завершению.
Если вы передали информацию, относящуюся к блоку управления (аналогично), то этот блок управления (вероятно) должен отслеживать, какая операция завершена, чтобы он знал, что делать дальше. Сам IOCP не знает и не заботится.
Если вы пишете сервер, подключенный к Интернету, сервер будет выдавать чтение, чтобы дождаться ввода от клиента. Этот ввод может поступить через миллисекунду или неделю спустя, и когда это произойдет, IOCP выпустит процедуру завершения, которая анализирует ввод. Обычно он отвечает записью, содержащей данные, запрошенные на входе, а затем ожидает IOCP. Когда запись завершена, IOCP снова освобождает процедуру завершения, которая видит, что запись завершена, (обычно) выдает новое чтение и запускается новый цикл.
Таким образом, приложение на основе IOCP обычно потребляет очень мало (или совсем не потребляет) ЦП до момента завершения, когда процедура завершения идет полным ходом, пока не завершит обработку, отправит новый запрос ввода-вывода и снова ждет порта завершения. . За исключением тайм-аута IOCP (который может использоваться для сигнализации служебного или подобного) все связанные с вводом-выводом вещи происходят в ОС.
Чтобы еще больше усложнить (или упростить) вещи, нет необходимости, чтобы сокеты обслуживались с помощью подпрограмм WSA, функции Win32 ReadFile и WriteFile работают нормально.
person
Olof Forshell
schedule
15.08.2013