LINUX.ORG.RU

взаимодействие нескольких select(poll/epoll) в разных нитях


0

0

под linux-ом
имеем некоторое количество сокетов
если не принимать во внимание расходы на переключение контекста нитей, то насколько будет отличатся ситуация:
ждем события на всех сокетах в одной нити или
запускаем , скажем, 10 нитей, и в каждой ждем свою часть сокетов
(предельный случай: для каждого сокета своя нить и свой select)


Ответ на: комментарий от asgard

блокирующий-не блокирующий
в данном контексте совершенно не важно
ибо данные я жду через select(poll,epoll)
и поведение этих сокетов отличается только в ситуации отсутствия данных
блокирующий будет спать пока они не прийдут, а неблокирующий вернет EAGAIN
вопрос в другом
если сокетов много, и активность большая
то что будет выгоднее, ждасть все в одном select или на каждый выделить свой(в отдельной нити)
с промежуточными вариантами
просто я думаю, чо уже этот ыопрос кто-нибудь решал
и нашел оптимальный вариант

before
() автор топика

не связывайся с нитями. По крайней мере пока количество одновременно прослушиваемых сокетов не станет *ЗАМЕТНО* превышать 1000.
Хотя и тогда стоит 100 раз подумать прежде чем с ними связыватся.

хотя если ты под нитями понимает не pthread тогда я неправ

Но новая ли эта проблема? Алан Кокс ещё в 2001-м году писал:

"В сущности, есть только два оправдания использованию тредов(нитей) в программировании.
1) Слабая подготовка программиста или слаборазвитые
средства обработки событий в языке программирования.
2) Проблемы в реализации отдельных компонентов ОС (а в posix/sus unix API таковые есть)

Использование Co-routines или _выбор более подходящего языка_ являются гораздо более эффективными решения проблемы обработки событий.

(Источник: http://marc.info/?l=linux-kernel&m=99254377501835&w=2)

А вот ещё крылатая фраза, взятая с домашней странички Larry McVoy: "A computer is a state machine. Threads are for people who can't program
state machines."

cvv ★★★★★
()
Ответ на: комментарий от cvv

А вот ещё крылатая фраза, взятая с домашней странички Larry McVoy: "A computer is a state machine. Threads are for people who can't program
state machines."

+1 :)

Etim sejchas i zanimayus' (FSM).

anonymous
()

Так, как ты хочешь, не имеет смысла делать, поскольку это будет "несправедливо" (fairness нарушится). Допустим, есть 4 сокета и два потока, 1-й и 2-й обслуживаются одним потоком, 3-й и 4-й - другим. Если загрузка по 1-му и 2-му сокету большая, а по 3-му и 4-му нет вообще, то второй поток будет простаивать, в то время как первый поток, возможно, не будет справляться. Если бы сокеты были сгруппированы по потокам так - (1, 3) и (2, 4), то общая пропускная способность (throughput) системы могла бы быть выше. Таким образом, твоя схема плоха тем, что пропускная способность зависит от совершенно искусственного фактора - как сокеты разложатся по группам.

Почитай в интернете про паттерн Reactor в связке с Leader-Follower. Вкратце идея такая: есть пул потоков, из которых только один в одно время выполняет select() на всем множестве сокетов, а остальные потоки спят. Когда select возвращает управление, этот поток берет первый "сработавший" дескриптор из множества, которое вернул select и начинает его обрабатывать, но перед этим "пробуждает" один, произвольно выбранный поток из пула, и передает ему оставшийся набор "сработавших" дескрипторов. Этот проснувшийся поток выбирает еще один дескриптор из набора и начинает обработку на нем, а перед тем "будит" следующий поток из пула - и т.д. Последний поток, которому "сработавших" дескрипторов не досталось, запустит select. Конечно, настоящая реализация несколько сложнее, но идея именно такая. Эта схема лишена недостатка, о котором я написал выше.

anonymous
()

в любом случае, нити в данном контексте наврятли принесут бенефит, бо всё равно всё упирается в пропускную способность сетевой карточки.

asgard
()
Ответ на: комментарий от cvv

> Алан Кокс ещё в 2001-м году писал:

Но есть люди, которые до сих пор не поняли шутку

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

>>Почитай в интернете про паттерн Reactor в связке с Leader-Follower.

Спасибо за инфу, интересный алгоритм.

amorphis
()
Ответ на: комментарий от cvv

> не связывайся с нитями. По крайней мере пока количество одновременно прослушиваемых сокетов не станет *ЗАМЕТНО* превышать 1000. Хотя и тогда стоит 100 раз подумать прежде чем с ними связыватся.

можно услышать технические обоснование вашего утверждения? что-то отличное от ссылок на чиста пацанов но ближе к конкретике. что, где, когда и почему.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от before

Из моего опыта, для обработки NONBLOCKING сокетов в poll достаточно одного треда даже при достаточно высоких нагрузках.

anonymous
()
Ответ на: комментарий от anonymous

>Почитай в интернете про паттерн Reactor в связке с Leader-Follower. Вкратце идея такая: есть пул потоков, из которых только один в одно время выполняет select() на всем множестве сокетов, а остальные потоки спят. Когда select возвращает управление, этот поток берет первый "сработавший" дескриптор из множества, которое вернул select и начинает его обрабатывать, но перед этим "пробуждает" один, произвольно выбранный поток из пула, и передает ему оставшийся набор "сработавших" дескрипторов. Этот проснувшийся поток выбирает еще один дескриптор из набора и начинает обработку на нем, а перед тем "будит" следующий поток из пула - и т.д. Последний поток, которому "сработавших" дескрипторов не досталось, запустит select. Конечно, настоящая реализация несколько сложнее, но идея именно такая. Эта схема лишена недостатка, о котором я написал выше.

Хм, ИМХО получиться больщой оверхэд на перключение контекста потоков. Считаю лучше использовать такой вариант:

1) Один поток на обработку "множества" сокетов в select.

2) Несколько потоков(workers) выполняющих бизнес логику. Количество воркеров желательно не должно быть больше чем количество физ. процессоров в системе. При этом надо понимать, что воркеры не имеют права блокироваться. Например если воркеру потребуется писать/читать файл или обращаться к СУБД - для таких операций прийдеться заводить отдельный поток(и) (и тоже производить обмен данных через очередь).

3) Взаимодействие сетевой поток <--> воркеры выполнять через две очереди input/output защишенных mutex'ом.

При такой схеме "утилизируется" 100% процессора(ов) и нет сильного оверхеда на переключении контенкста потоков.

anonymous
()
Ответ на: комментарий от anonymous

>Почитай в интернете про паттерн Reactor в связке с Leader-Follower. Вкратце идея такая: есть пул потоков, из которых только один в одно время выполняет select() на всем множестве сокетов, а остальные потоки спят. Когда select возвращает управление, этот поток берет первый "сработавший" дескриптор из множества, которое вернул select и начинает его обрабатывать, но перед этим "пробуждает" один, произвольно выбранный поток из пула, и передает ему оставшийся набор "сработавших" дескрипторов. Этот проснувшийся поток выбирает еще один дескриптор из набора и начинает обработку на нем, а перед тем "будит" следующий поток из пула - и т.д. Последний поток, которому "сработавших" дескрипторов не досталось, запустит select. Конечно, настоящая реализация несколько сложнее, но идея именно такая. Эта схема лишена недостатка, о котором я написал выше.

Да и вот еще проблема: к примеру мы имеем 4 потока, к нам приходит 4 "тяжелых задания" выполняния которых потребует нескольких секунд. Так вот, на время выполнения этих заданий сеть обрабатыватся не будет т.к. все потоки будут заняты и некому будет запустить select. А если за это время прийдет больше новых клиентских коннектов чем длина кернельной очереди для not accepted в user-space сокетов (параметр backlog в listen) - клиенты вообще получат connection refused:)

Можно конечно возразить, что проблему можно решить создав не 4 а 444 потока:) Но мне кажется это не правильно.

Кроме того не ясно как при такой схеме удалять читать/писать/добавлять/удалять сокеты из множества из разных потоков. Защищать множество mutex'ом и самому защишаться от dedlock'ов?

anonymous
()
Ответ на: комментарий от ero-sennin

пускаем по процессу на CPU с привязкой к CPU. Меня последним временем склонили к мысли что разделять процес на потоки имеет смысл только в пределах одного ядра CPU. Тоесть не размазывать процесс на несколько ядер.

2 klalafuda: Это остаточные знания. Я потоками не занимался года два и посему с конкретикой будет напряг.

Ещё рекомендую поразмышлять на тем почему нет удачных многопотоковых реализаций X-серверов. Оба X-Free86 && X-Org однопоточные.

cvv ★★★★★
()
Ответ на: комментарий от cvv

>По крайней мере пока количество одновременно прослушиваемых сокетов не станет *ЗАМЕТНО* превышать 1000

я расчитываю на >10_000 соединений

> ... или слаборазвитые средства обработки событий в языке программирования.

событийная машина, это теже нити, только неявные

>2) Несколько потоков(workers) выполняющих бизнес логику. Количество воркеров желательно не должно быть больше чем количество физ. процессоров в системе. При этом надо понимать, что воркеры не имеют права блокироваться. Например если воркеру потребуется писать/читать файл или обращаться к СУБД - для таких операций прийдеться заводить отдельный поток(и) (и тоже производить обмен данных через очередь).

до обработки входящего сообщения, я не могу знать, потребуются ли для работы блокируемые операции или нет

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

>Ещё рекомендую поразмышлять на тем почему нет удачных многопотоковых реализаций X-серверов. Оба X-Free86 && X-Org однопоточные.

1) потому что они разрабытывались в то время когда были только userlevel threading

2) переносимость кода

before
() автор топика
Ответ на: комментарий от before

>> ... или слаборазвитые средства обработки событий в языке программирования.

>событийная машина, это теже нити, только неявные

естественно. Только проблем и возни с ними на порядок меньше

>1) потому что они разрабытывались в то время когда были только userlevel threading

многопотоковые Х-сервера разрабатывались в то время когда был только userlevel threading? а те которые после появления нативных/posix тредов? в солярке скажем pthread уже давненько поддерживается да и линукс не сильно отстаёт... а мы всё на X-Free/X-Org

cvv ★★★★★
()
Ответ на: комментарий от cvv

>>> ... или слаборазвитые средства обработки событий в языке программирования.

>>событийная машина, это теже нити, только неявные

>естественно. Только проблем и возни с ними на порядок меньше

тем самым опровергается первая причина саюжевого утверждения

>а мы всё на X-Free/X-Org

сколько времени существуют нативные нити в линуксе? и сколько времени существуют иксы?

кто возьмется все переписать под нативные нити? и сколько времени это займет?

уж лучше песть будет то что есть и то что работает

before
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.