Подтвердить что ты не робот

Существует ли проблема грозового стада в Linux?

Многие книги и учебники по Linux/Unix говорят о "Проблема грозового стада" , которая происходит, когда несколько потоков или вилок блокируются при выборе(), ожидая удобочитаемости прослушивающего сокета. Когда соединение приходит, все потоки и вилки разбужаются, но только один "выигрывает" с успешным вызовом "accept()". Тем временем, много времени процессора теряется впустую, пробуждая все потоки/вилки без причины.

Я заметил project, который обеспечивает "исправление" этой проблемы в ядре linux, но это очень старый патч.

Я думаю, что есть два варианта; Один, где каждая вилка делает select(), а затем принимает(), и тот, который просто принимает().

У современных ядер unix/linux все еще есть проблема Громового Стада в обоих этих случаях или только версия "select() then accept()"?

4b9b3361

Ответ 1

В течение многих лет большинство ядер unix/linux сериализуют ответ на accept (2) s, другими словами, только один поток пробуждается, если более одного блокируют accept (2) против одного открытого описания файла.

OTOH, многие (если не все) ядра по-прежнему имеют проблему громоподобного стада в шаблоне select-accept, как вы описываете.

Я написал простой script (https://gist.github.com/kazuho/10436253), чтобы проверить существование проблемы, и выяснил, что проблема существует в Linux 2.6.32 и Darwin 12.5.0 (OS X 10.8.5).

Ответ 2

Это очень старая проблема, и по большей части ее больше не существует. Ядро Linux (за последние несколько лет) имеет ряд изменений в том, как он обрабатывает и направляет пакеты в сетевой стек, и включает в себя множество оптимизаций для обеспечения как низкой латентности, так и справедливости (т.е. Минимизации голода).

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

В настоящее время предпочтительным способом создания асинхронного ввода-вывода является epoll. API намного проще и очень хорошо масштабируется для различных типов нагрузки (многие соединения, большая пропускная способность и т.д.).

Ответ 3

Недавно я увидел протестированный сценарий, в котором несколько потоков опросили прослушивающий сокет unix-домена, а затем приняли соединение. Все потоки проснулись с использованием системного вызова poll().

Это была обычная сборка ядра linux, а не сборка дистрибутива, поэтому, возможно, есть опция настройки ядра, которая меняет ее, но я не знаю, что бы это было.

Мы не пробовали epoll.

Ответ 4

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

http://lwn.net/Articles/632590/