Предостережения о выборе / опросе против реактора Эполла в Twisted - PullRequest
89 голосов
/ 09 января 2010

Все, что я прочитал и испытал (приложения на основе Tornado), наводит меня на мысль, что ePoll - естественная замена для сетей на основе Select и Poll, особенно с Twisted. Что делает меня параноиком, это редкость, когда лучшая техника или методология не имеют цены.

Чтение пары дюжин сравнений между epoll и альтернативами показывает, что epoll явно побеждает в скорости и масштабируемости, особенно в том, что он масштабируется линейно, что является фантастическим. Тем не менее, как насчет использования процессора и памяти, epoll по-прежнему лидирует?

Ответы [ 2 ]

184 голосов
/ 09 января 2010

Для очень небольшого количества сокетов (конечно, зависит от вашего оборудования, но мы говорим о чем-то порядка 10 или меньше), select может превзойти epoll в использовании памяти и скорости выполнения. Конечно, для такого небольшого количества сокетов оба механизма настолько быстры, что в большинстве случаев вас не волнует это различие.

Одно уточнение. И выберите, и эполл масштабировать линейно. Однако большая разница заключается в том, что API, ориентированные на пользовательское пространство, имеют сложности, основанные на разных вещах. Стоимость вызова select примерно соответствует значению дескриптора файла с наибольшим номером, который вы передаете. Если вы выберете один fd, 100, то это примерно в два раза дороже, чем выбор одного fd, 50. Добавление большего количества fds ниже самого высокого уровня не совсем бесплатно, так что на практике это немного сложнее, чем это, но это является хорошим первым приближением для большинства реализаций.

Стоимость epoll ближе к количеству файловых дескрипторов, в которых действительно есть события. Если вы отслеживаете 200 файловых дескрипторов, но только у 100 из них есть события, то вы (очень грубо) платите только за эти 100 активных файловых дескрипторов. Именно здесь epoll имеет тенденцию предлагать одно из основных преимуществ по сравнению с select. Если у вас есть тысяча клиентов, которые в основном бездействуют, то при использовании select вы все равно платите за все тысячу из них. Однако в случае epoll у вас есть только несколько - вы платите только за те, которые активны в любой момент времени.

Все это означает, что epoll приведет к меньшему использованию процессора для большинства рабочих нагрузок. Что касается использования памяти, это немного сложно. select удается представить всю необходимую информацию в очень компактном виде (один бит на дескриптор файла). А ограничение FD_SETSIZE (обычно 1024) на количество файловых дескрипторов, которые вы можете использовать с select, означает, что вы никогда не потратите более 128 байтов на каждый из трех наборов fd, которые вы можете использовать с select (чтение, запись, исключение). По сравнению с этими 384 байтами максимум, epoll - своего рода свинья. Каждый дескриптор файла представлен многобайтовой структурой. Тем не менее, в абсолютном выражении, он по-прежнему не будет использовать много памяти. Вы можете представить огромное количество файловых дескрипторов в несколько десятков килобайт (я думаю, примерно 20 тыс. На 1000 файловых дескрипторов). И вы также можете добавить тот факт, что вам нужно потратить все 384 из этих байтов с select, если вы хотите отслеживать только один дескриптор файла, но его значение равно 1024, тогда как с epoll вы потратите всего 20 байтов. Тем не менее, все эти цифры довольно малы, поэтому это не имеет большого значения.

И есть еще одно преимущество epoll, о котором вы, возможно, уже знаете, что оно не ограничивается дескрипторами файлов FD_SETSIZE. Вы можете использовать его для мониторинга столько файловых дескрипторов, сколько у вас есть. И если у вас есть только один дескриптор файла, но его значение больше, чем FD_SETSIZE, epoll также работает с этим, но select - нет.

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

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

На практике единственное место, где я видел это, - это взаимодействие со stdio. Пользователь может перенаправить стандартный или стандартный вывод из / в обычный файл. В то время как ранее stdin и stdout были бы конвейером - он прекрасно поддерживал epoll - тогда он становился обычным файлом и epoll громко терпел неудачу, ломая приложение.

4 голосов
/ 30 апреля 2014

В тестах в моей компании возникла одна проблема с epoll (), таким образом, единственная стоимость по сравнению с select.

При попытке чтения из сети с тайм-аутом создание epoll_fd (вместо FD_SET) и добавление fd к epoll_fd намного дороже, чем создание FD_SET (который является простым malloc).

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

Этот тип использования редко встречается в высокопроизводительных приложениях, потому что модели реактора не нужно каждый раз создавать новый epoll_fd. Для модели, в которой epoll_fd является долгоживущим - что явно предпочтительнее для любого высокопроизводительного дизайна сервера - epoll - явный победитель во всех отношениях.

...