Как работает epoll?

Слово epoll сейчас определенно на слуху, в первую очередь благодаря росту популярности неблокирующих HTTP-серверов. При этом мало кто пытается разобраться в том, что, собственно, за ним стоит и почему использующие этот механизм продукты, среди которых достойное место занимают, например, nginx, node.js и Tornado, так значительно выигрывают в производительности у ближайших альтернатив. Хотите копнуть глубже?

О чем пойдет речь?

 

  • epoll является масштабируемой неблокирующей системой уведомления о собятиях ввода-вывода в Linux. В отличии от более старых механизмов, у epoll время срабатывания не зависит от количества открытых файловых дескрипторов.
  • epoll используется для обработки событий неблокирующих TCP-сокетов, операционная система оповещает приложение когда один из сокетов «под наблюдением» готов получить или отправить сообщение. В традиционном же подходе на каждый сокет выделяется поток выполнения (thread), который блокируется до возвращения обращения к соответствующему сокету.

 

Сразу хочу предупредить, хоть на практике epoll и используется чаще, существуют и альтернативные реализации схожего подхода, например kqueue в BSD системах. Конечные продукты обычно используют библиотеку, абстрагирующуе низкоуровневые вызовы, наиболее распросраненные - libev и libevent.

 

Что это дает?

 

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

 

Обратная сторона медали

 

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

 

На пальцах

 

Вернемся к изначальному вопросу статьи: Как работает epoll? Давайте попробуем разобрать на простом примере.

 

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

 

Блокирующий (традиционный)

 

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

 

Вы ограничены как количеством печей, так и количеством помощников, которые могут поместиться в вашей пиццерии.

 

Неблокирующий (epoll и аналоги)

 

Вы принимаете заказ, ставит пиццу в печь и ставите таймер (операционная система посредством epoll), чтобы узнать когда пицца испечется. После чего Вы возвращаетесь к приему заказов. Как только прозвенел таймер — Вы идете к соответствующей печи, достаете пиццу и отдаете заказчику, после чего снова возвращаетесь к приему заказов.

 

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

 

Заключение

 

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

www.insight-it.ru/tekhnologii/kak-rabotaet-epoll/

Вверх