К вопросу использования #epoll вместо хорошо знакомых и «традиционных» select/poll.
Недавно пришлось заниматься реализацией своей очереди событий для AMQP-CPP.
В одном из продуктов решено сделать связь агентских частей с основным «контроллером» через #AMQP. В качестве брокера выбран #RabbitMQ (всё стандартно, обычный кластер и TLS-соединения).
Вот только агенты продукта активно используют асинхронное программирование с хорошей «горизонтальной масштабируемостью». Когда не только lock-free или wait-free, но и полноценное sharing nothing. Учитывается не только закон Амдала, но исключается и старый-добрый cache ping-pong и того же false sharing.
Отсюда, внутри агентов своё управление потоками и выделениями памяти. Не только в плане heap (динамической памяти), со своими аллокаторами а-ля #jemalloc от #Facebook, но и приколы вокруг нод #NUMA и даже huge pages (меньше нагрузки на #TLB, «давления» и промахов).
Первая же проблема выплыла почти сразу — не реально использовать библиотеку AMQP-CPP. Вообще и в целом не подходят библиотеки использующие традиционные очереди сообщений #libev, #libuv, #libevent. Несовместимы с имеющейся моделью управления потоками и организации шетдулинга задач.
Был взят epoll, просто с того, что меньше копирований памяти между user space и kernel. А при появлении данных в дескрипторе событие может содержать указатель прямо на структуру данных, где лежит объект #tcp соединения. Того самого, в которое пришли данные.
Вторая проблема обозначилась тогда, когда стало ясно, что AMQP-библиотека не вычитывает данные целиком из потока сокета. Например, забирает данные лишь до тех пор, пока не насытится автомат состояний (finite-state machine), выполняющий парсинг сущностей протокола.
Мораль?Нельзя использовать работу «по фронту» (edge-triggered) не будучи знакомым досканально с внутренностями чужой библиотики. Используя epoll почти наверняка придётся ориентироваться на работу «по уровню» (level-triggered). А увидев использование флага EPOLLET автоматом поднимать вопрос, а была ли тщательно и досканально изучена работа чужого кода. Есть ли достаточные основания для включения режима работы epoll через выбрасывания событий «по фронту» (edge-triggered).
Про Edge Triggered Vs Level Triggered interrupts можно почитать в https://venkateshabbarapu.blogspot.com/2013/03/edge-triggered-vs-level-triggered.html)