Предостережения select / poll против epoll реакторов в Twisted


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

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

2 88

2 ответа:

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

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

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

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

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

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

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

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

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

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

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

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