Вращение в неблокирующем приложении без затрат времени на процессор - PullRequest
1 голос
/ 13 апреля 2011

У меня есть сетевое приложение UDP, которое читает отправленные ему пакеты и затем обрабатывает их (тот же поток).Чтения не блокируют, поэтому я не использую poll или select.

Полученные пакеты группируются по сеансам.

Работа определяется тем, идет ли сеанс в процессе.Если нет никакой работы, то есть нет сеансов или нет пакетов для обработки, тогда мне нужно вращаться.

Я смотрел на гибридный алгоритм, найденный здесь: http://www.1024cores.net/home/lock-free-algorithms/tricks/spinning

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

РЕДАКТИРОВАТЬ:

Спасибо за все ответы и комментарии.Я сейчас делаю следующее.Когда дело доходит до чтения из сети, я смотрю, есть ли другая работа, которую нужно сделать.Если есть, то я вызываю опрос с таймаутом, равным нулю.Затем я читаю как можно больше пакетов и помещаю их в очередь в памяти для обработки.Если нет другой работы, то я опрашиваю неопределенно (т.е. -1).Кажется, он работает хорошо, процессор загружается только тогда, когда все занято, иначе он падает до нуля.

Ответы [ 3 ]

3 голосов
/ 13 апреля 2011

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

Спиннинг - это то, что вы должны делать, только когда ожидаете очень короткого промежутка времени (обычно только в режиме ядра).

1 голос
/ 13 апреля 2011

Сколько пакетов в секунду вы обрабатываете? Сколько времени занимает обработка этих пакетов? Если вы используете блокирующие потоки, какое среднее использование процессора вы получаете?

Если ожидание блокировки близко к 100% использованию, где может помочь снижение производительности на несколько битов от самой блокировки, вращение не улучшит, а скорее ухудшит производительность. Вращаясь, вы блокируете одно ядро, которое не будет доступно для запуска другого кода (возможно, включая код, который питает вас работой: то есть код ядра, который читает сеть и передает в ваше приложение пакеты), вы сжигаете ресурсы, не выполняя никакой работы. вообще ...

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

Кроме того, если стоимость проверки условия высока, тогда спиннинг повлечет за собой эту стоимость для каждой итерации цикла, и это может значительно превысить стоимость проверки один раз и выполнения дорогого * 1008. * подождите.

Помните, что вращение - это активное ожидание , не имеет смысла спрашивать, как активно ожидать , пока не потребляет процессор, поскольку подход активного ожидания подразумевает потребляет процессорное время. Что вы можете сделать, чтобы избежать ненужной загрузки ЦП? Используйте блокирующий вызов для получения следующего пакета. В конкретном случае чтения UDP-пакета я сомневаюсь, что два вызова неблокирующего чтения не дороже по времени обработки, чем один вызов блокирующего чтения.

Снова подумайте над вопросами в начале, которые можно подытожить следующим образом: Является ли блокирование узким местом? * Это сценарий, в котором активные ожидания могут действительно помочь? *

1 голос
/ 13 апреля 2011

Поскольку вы должны читать из сокета, вы можете просто выполнить блокировку чтения.Без пакета у вас нет причин для запуска, верно?

Если имеется более одного сокета, блокирующее чтение не будет работать, поэтому вам нужно pselect () дляконтролировать несколько дескрипторов.

Я что-то упускаю из виду?

Мне приходит в голову, что у вас может быть длительная обработка после получения do дейтаграммы.Если причина, по которой вы используете неблокирующий ввод-вывод, состоит в том, чтобы избежать игнорирования входящего трафика во время работы над сеансом, то в этом случае очевидная вещь, которую нужно сделать, - это fork () сеансов.(Хм, так что я все еще думаю, что я что-то упускаю ...)

...