[Python-checkins] cpython: Issue #16876: Optimize epoll.poll() by keeping a per-instance epoll events

charles-francois.natali python-checkins at python.org
Wed Jan 9 19:00:55 CET 2013


http://hg.python.org/cpython/rev/be8e6b81284e
changeset:   81341:be8e6b81284e
user:        Charles-François Natali <neologix at free.fr>
date:        Wed Jan 09 19:00:26 2013 +0100
summary:
  Issue #16876: Optimize epoll.poll() by keeping a per-instance epoll events
buffer instead of allocating a new one at each poll().

files:
  Misc/NEWS              |   3 ++
  Modules/selectmodule.c |  45 +++++++++++++++++++++--------
  2 files changed, 35 insertions(+), 13 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -212,6 +212,9 @@
 Library
 -------
 
+- Issue #16876: Optimize epoll.poll() by keeping a per-instance epoll events
+  buffer instead of allocating a new one at each poll().
+
 - Issue #16491: IDLE now prints chained exception tracebacks.
 
 - fcntl: add F_DUPFD_CLOEXEC constant, available on Linux 2.6.24+.
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -1056,9 +1056,14 @@
 #include <sys/epoll.h>
 #endif
 
+/* default maximum number of events returned by epoll_wait() */
+#define EPOLL_DEFAULT_MAXEVENTS (FD_SETSIZE)
+
 typedef struct {
     PyObject_HEAD
-    SOCKET epfd;                        /* epoll control file descriptor */
+    SOCKET epfd;                    /* epoll control file descriptor */
+    int maxevents;                  /* maximum number of epoll events */
+    struct epoll_event *evs;        /* epoll events buffer */
 } pyEpoll_Object;
 
 static PyTypeObject pyEpoll_Type;
@@ -1114,6 +1119,15 @@
         PyErr_SetFromErrno(PyExc_OSError);
         return NULL;
     }
+
+    self->maxevents = EPOLL_DEFAULT_MAXEVENTS;
+    self->evs = PyMem_New(struct epoll_event, self->maxevents);
+    if (!self->evs) {
+        Py_DECREF(self);
+        PyErr_NoMemory();
+        return NULL;
+    }
+ 
     return (PyObject *)self;
 }
 
@@ -1140,6 +1154,10 @@
 pyepoll_dealloc(pyEpoll_Object *self)
 {
     (void)pyepoll_internal_close(self);
+    if (self->evs) {
+        PyMem_Free(self->evs);
+        self->evs = NULL;
+    }
     Py_TYPE(self)->tp_free(self);
 }
 
@@ -1320,7 +1338,6 @@
     int maxevents = -1;
     int nfds, i;
     PyObject *elist = NULL, *etuple = NULL;
-    struct epoll_event *evs = NULL;
     static char *kwlist[] = {"timeout", "maxevents", NULL};
 
     if (self->epfd < 0)
@@ -1344,24 +1361,27 @@
     }
 
     if (maxevents == -1) {
-        maxevents = FD_SETSIZE-1;
-    }
-    else if (maxevents < 1) {
+        maxevents = EPOLL_DEFAULT_MAXEVENTS;
+    } else if (maxevents < 1) {
         PyErr_Format(PyExc_ValueError,
                      "maxevents must be greater than 0, got %d",
                      maxevents);
         return NULL;
     }
+    if (maxevents > self->maxevents) {
+        struct epoll_event *orig_evs = self->evs;
 
-    evs = PyMem_New(struct epoll_event, maxevents);
-    if (evs == NULL) {
-        Py_DECREF(self);
-        PyErr_NoMemory();
-        return NULL;
+        PyMem_RESIZE(self->evs, struct epoll_event, maxevents);
+        if (!self->evs) {
+            self->evs = orig_evs;
+            PyErr_NoMemory();
+            return NULL;
+        }
+        self->maxevents = maxevents;
     }
 
     Py_BEGIN_ALLOW_THREADS
-    nfds = epoll_wait(self->epfd, evs, maxevents, timeout);
+    nfds = epoll_wait(self->epfd, self->evs, self->maxevents, timeout);
     Py_END_ALLOW_THREADS
     if (nfds < 0) {
         PyErr_SetFromErrno(PyExc_OSError);
@@ -1374,7 +1394,7 @@
     }
 
     for (i = 0; i < nfds; i++) {
-        etuple = Py_BuildValue("iI", evs[i].data.fd, evs[i].events);
+        etuple = Py_BuildValue("iI", self->evs[i].data.fd, self->evs[i].events);
         if (etuple == NULL) {
             Py_CLEAR(elist);
             goto error;
@@ -1383,7 +1403,6 @@
     }
 
     error:
-    PyMem_Free(evs);
     return elist;
 }
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list