Эффективный перекрывающийся ввод-вывод для сокет-сервера - PullRequest
2 голосов
/ 12 февраля 2011

Какая из этих двух разных моделей будет более эффективной (например, обмолот, использование кэша процессора, общий дизайн, все и т. Д.)?

  1. 1 IOCP и ускорение потоков X (где X - количество процессоров, установленных на компьютере).Это будет означать, что мой «сервер» будет иметь только 1 IOCP (очередь) для всех запросов и X потоков для их обслуживания / обработки.Я прочитал много статей, обсуждающих эффективность этого дизайна.С этой моделью у меня был бы 1 слушатель, который также был бы связан с IOCP.Давайте предположим, что я мог бы выяснить, как синхронизировать пакеты / запросы.

  2. X IOCP (где X - количество процессоров в компьютере), и каждый IOCP имеет 1 поток.Это будет означать, что у каждого процессора есть своя очередь и 1 поток для их обслуживания / обработки.В этой модели у меня будет отдельный прослушиватель (не использующий IOCP), который будет обрабатывать входящие соединения и назначать SOCKET для соответствующего IOCP (один из созданных X).Предположим, что я смог выяснить распределение нагрузки.

Используя слишком упрощенную аналогию для двух проектов (банк):

  1. ОдинЛиния с несколькими кассирами для передачи транзакций.Каждый человек находится в одной строке, и каждый кассир берет следующего доступного человека в строке.

  2. Каждый кассир имеет свою собственную линию, и люди «помещаются» в одну из этих линий

Между этими двумя конструкциями, который является более эффективным.В каждой модели перекрывающиеся структуры ввода-вывода будут использовать VirtualAlloc с MEM_COMMIT (в отличие от «нового»), поэтому файл подкачки не должен быть проблемой (без подкачки страниц).Основываясь на том, как это было мне описано, используя VirtualAlloc с MEM_COMMIT, память резервируется и не выгружается.Это позволило бы СОКЕТАМ записывать входящие данные прямо в мои буферы, не проходя промежуточные слои.Поэтому я не думаю, что побои должны быть фактором, но я могу ошибаться.

Кто-то говорил мне, что # 2 будет более эффективным, но я не слышал об этой модели.Заранее спасибо за ваши комментарии!

Ответы [ 2 ]

2 голосов
/ 12 февраля 2011

Я предполагаю, что для # 2 вы планируете вручную связать свои сокеты с IOCP, который, по вашему мнению, является «лучшим» на основе некоторой меры «добродетели» в момент принятия сокета?И что каким-то образом эта мера «добродетели» будет сохраняться на протяжении всего срока службы сокета?

С IOCP использовался «стандартный» способ, т. Е. Ваш вариант № 1, ядро ​​решает, как лучше использовать потоки, которые вы используете.иметь и позволяет больше работать, если любой из них заблокировать.С вашим методом, если вы как-то решите, как распределить работу, вы получите больше потоков, чем с опцией 1.

Ваша опция # 2 также не позволяет использовать AcceptEx() для перекрытияпринимает, и это более эффективно, чем использование обычного цикла принятия, когда вы удаляете поток (и результирующее переключение контекста и потенциальную конкуренцию) со сцены.

Ваша аналогия нарушается;на самом деле это скорее случай наличия 1 очереди с кассирами Х-банка, когда вы присоединяетесь к очереди и знаете, что вас будут видеть в эффективном порядке, в отличие от каждого кассира, имеющего свою очередь, и вам придется угадывать, что очередь, к которой вы присоединяетесьне содержит целую группу людей, которые хотят открыть новые учетные записи, а рядом с вами находится целая группа людей, которые хотят только внести некоторые платежи. Единая очередь гарантирует, что вы будете обрабатываться эффективно.

Я думаю, что вы не уверены в MEM_COMMIT.Это не означает, что память не находится в файле подкачки и не будет выгружена.Обычная причина использования VirtualAlloc для перекрывающихся буферов состоит в том, чтобы обеспечить выравнивание по границам страниц и, таким образом, уменьшить количество страниц, заблокированных для ввода-вывода (буфер размера страницы может быть размещен на границе страницы, поэтому занимает только одну страницувместо того, чтобы охватывать два из-за того, что менеджер памяти решил использовать блок, который не начинается на границе страницы).

В общем, я думаю, что вы пытаетесь оптимизировать что-то с опережением графика.Получите эффективный сервер, работающий с использованием IOCP сначала обычным способом, а затем профилируйте его.Я серьезно сомневаюсь, что вам даже придется беспокоиться о сборке версии №2 ... Аналогичным образом, используйте new, чтобы выделить ваши буферы для начала, а затем переключитесь на дополнительную сложность VirtualAlloc(), когда вы обнаружите, что ваш серверпроисходит сбой из-за ENOBUFS, и вы уверены, что это связано с лимитом заблокированных страниц ввода-вывода, а не с отсутствием невыгружаемого пула (вы действительно понимаете, что для VirtualAlloc() нужно выделять фрагменты размером «гранулярность выделения»?).

В любом случае, у меня есть бесплатный серверный фреймворк IOCP, доступный здесь: http://www.serverframework.com/products---the-free-framework.html, который может помочь вам начать работу.

Отредактировано: Комплекспредлагаемая версия может быть полезна в некоторых архитектурах NUMA, где вы используете группирование сетевых адаптеров, чтобы коммутатор распределял трафик между несколькими сетевыми картами, связывал каждый сетевой адаптер с различным физическим процессором, а затем связывал потоки IOCP с одним и тем же процессором.Затем вы распределяете память от этого узла NUMA и эффективно заставляете свой сетевой коммутатор распределять нагрузку на ваши соединения между вашими узлами NUMA.Я бы по-прежнему предположил, что лучше, имхо, получить работающий сервер, который можно профилировать, используя «нормальный» метод использования IOCP в первую очередь, и только после того, как вы узнаете, что проблемы с несколькими узлами NUMA на самом деле влияют на вашу производительность в сторону более сложныхархитектура ...

0 голосов
/ 12 февраля 2011

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

Метод с несколькими очередями должен иметь лучшее поведение кеша. То, насколько оно лучше, зависит от того, сколько принятых пакетов связано с одной транзакцией. Если запрос помещается в один входящий пакет, он будет связан с одним потоком даже при одном подходе IOCP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...