mirror of https://github.com/python/cpython
Issue #16876: Optimize epoll.poll() by keeping a per-instance epoll events
buffer instead of allocating a new one at each poll().
This commit is contained in:
parent
0b32a480bd
commit
f424f3856d
|
@ -212,6 +212,9 @@ Core and Builtins
|
||||||
Library
|
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.
|
- Issue #16491: IDLE now prints chained exception tracebacks.
|
||||||
|
|
||||||
- fcntl: add F_DUPFD_CLOEXEC constant, available on Linux 2.6.24+.
|
- fcntl: add F_DUPFD_CLOEXEC constant, available on Linux 2.6.24+.
|
||||||
|
|
|
@ -1056,9 +1056,14 @@ static int select_have_broken_poll(void)
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* default maximum number of events returned by epoll_wait() */
|
||||||
|
#define EPOLL_DEFAULT_MAXEVENTS (FD_SETSIZE)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
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;
|
} pyEpoll_Object;
|
||||||
|
|
||||||
static PyTypeObject pyEpoll_Type;
|
static PyTypeObject pyEpoll_Type;
|
||||||
|
@ -1114,6 +1119,15 @@ newPyEpoll_Object(PyTypeObject *type, int sizehint, int flags, SOCKET fd)
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
return NULL;
|
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;
|
return (PyObject *)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1140,6 +1154,10 @@ static void
|
||||||
pyepoll_dealloc(pyEpoll_Object *self)
|
pyepoll_dealloc(pyEpoll_Object *self)
|
||||||
{
|
{
|
||||||
(void)pyepoll_internal_close(self);
|
(void)pyepoll_internal_close(self);
|
||||||
|
if (self->evs) {
|
||||||
|
PyMem_Free(self->evs);
|
||||||
|
self->evs = NULL;
|
||||||
|
}
|
||||||
Py_TYPE(self)->tp_free(self);
|
Py_TYPE(self)->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1320,7 +1338,6 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
|
||||||
int maxevents = -1;
|
int maxevents = -1;
|
||||||
int nfds, i;
|
int nfds, i;
|
||||||
PyObject *elist = NULL, *etuple = NULL;
|
PyObject *elist = NULL, *etuple = NULL;
|
||||||
struct epoll_event *evs = NULL;
|
|
||||||
static char *kwlist[] = {"timeout", "maxevents", NULL};
|
static char *kwlist[] = {"timeout", "maxevents", NULL};
|
||||||
|
|
||||||
if (self->epfd < 0)
|
if (self->epfd < 0)
|
||||||
|
@ -1344,24 +1361,27 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxevents == -1) {
|
if (maxevents == -1) {
|
||||||
maxevents = FD_SETSIZE-1;
|
maxevents = EPOLL_DEFAULT_MAXEVENTS;
|
||||||
}
|
} else if (maxevents < 1) {
|
||||||
else if (maxevents < 1) {
|
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"maxevents must be greater than 0, got %d",
|
"maxevents must be greater than 0, got %d",
|
||||||
maxevents);
|
maxevents);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (maxevents > self->maxevents) {
|
||||||
|
struct epoll_event *orig_evs = self->evs;
|
||||||
|
|
||||||
evs = PyMem_New(struct epoll_event, maxevents);
|
PyMem_RESIZE(self->evs, struct epoll_event, maxevents);
|
||||||
if (evs == NULL) {
|
if (!self->evs) {
|
||||||
Py_DECREF(self);
|
self->evs = orig_evs;
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
self->maxevents = maxevents;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
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
|
Py_END_ALLOW_THREADS
|
||||||
if (nfds < 0) {
|
if (nfds < 0) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
@ -1374,7 +1394,7 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nfds; i++) {
|
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) {
|
if (etuple == NULL) {
|
||||||
Py_CLEAR(elist);
|
Py_CLEAR(elist);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1383,7 +1403,6 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
PyMem_Free(evs);
|
|
||||||
return elist;
|
return elist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue