Hi, async programmers.

Linux 4.5 released in last month intorduces EPOLLEXCLUSIVE.
http://man7.org/linux/man-pages/man2/epoll_ctl.2.html

It can address epoll thundering herd problem.
http://uwsgi-docs.readthedocs.org/en/latest/articles/SerializingAccept.html#select-poll-kqueue-epoll

I tried it on AWS EC2 c4.xlarge (4core).

* simple "hello world" wsgi app
* Use uWSGI and meinheld with 8 workers
* ab -n10000 -c4

EPOLLEXCLUSIVE improve performance from 15k req/sec to 22k req/sec.

And I confirm it reduces number of `accept4()` call significantly.

ubuntu:~/app$ strace -f ~/.local/bin/uwsgi --master --workers=8 --http-socket 
:8080 --wsgi hello 2>trace.log
ubuntu:~$ ab -c1 -n1000 http://localhost:8080/
ubuntu:~/app$ grep -c '] accept4' trace.log  # w/o EPOLLEXCLUSIVE6884
ubuntu:~/app$ grep -c '] accept4' trace.log   # w/ EPOLLEXCLUSIVE1557



And I confirm Linux ~4.4 ignores EPOLLEXCLUSIVE (1 << 28).  So I can use it 
safely without compile time nor runtime check.

I want to add EPOLLEXCLUSIVE support to asyncio.
Current selector's API is:

abstractmethod register(fileobj, events, data=None)

https://docs.python.org/3/library/selectors.html#selectors.BaseSelector.register

How can I cange the API?

Maybe:

abstractmethod register(fileobj, events, data=None, **flags)
...
poller.register(listenfd, selectors.EVENT_READ, data, exclusive=True)  # 
only EpollSelector supports exclusive. others ignore unknown flags.


Or:

poller.register(listenfd, selectors.EVENT_READ_EXCLUSIVE, data)   # Add 
EVENT_READ_EXCLUSIVE and EVENT_READ_EXCLUSIVE.


Thanks.

---
pache for meinheld:

diff --git a/meinheld/server/picoev_epoll.c b/meinheld/server/picoev_epoll.c
index 06e1dbb..773cf3c 100644--- a/meinheld/server/picoev_epoll.c+++ 
b/meinheld/server/picoev_epoll.c@@ -115,6 +115,7 @@ int 
picoev_update_events_internal(picoev_loop* _loop, int fd, int events)
     SET(EPOLL_CTL_MOD, 0);
     if (epoll_ret != 0) {
       assert(errno == ENOENT);+      ev.events |= (1 << 28);  // 
EPOLLEXCLUSIVE (from linux 4.5)
       SET(EPOLL_CTL_ADD, 1);
     }
   }@@ -124,7 +125,12 @@ int picoev_update_events_internal(picoev_loop* _loop, 
int fd, int events)
   if ((events & PICOEV_READWRITE) == 0) {
     SET(EPOLL_CTL_DEL, 1);
   } else {-    SET(target->events == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, 1);+   
 if (target->events == 0) {+      ev.events |= (1 << 28);  // EPOLLEXCLUSIVE 
(from linux 4.5)+      SET(EPOLL_CTL_ADD, 1);+    } else {+      
SET(EPOLL_CTL_MOD, 1);+    }
   }

 #endif


pache for uWSGI:

diff --git a/core/event.c b/core/event.c
index 36751a6..32a1934 100644--- a/core/event.c+++ b/core/event.c@@ -514,7 
+514,7 @@ int event_queue_add_fd_read(int eq, int fd) {
        struct epoll_event ee;

        memset(&ee, 0, sizeof(struct epoll_event));-       ee.events = 
EPOLLIN;+       ee.events = EPOLLIN | (1 << 28);
        ee.data.fd = fd;

        if (epoll_ctl(eq, EPOLL_CTL_ADD, fd, &ee)) {


Reply via email to