aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2014-09-24 21:39:17 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2014-09-24 21:39:17 +0200
commit0e51b3741185055d5bb82adc314d89a1c15b64ae (patch)
tree817956686583d532d9524201b797d4caff1e7cab
parent49e7f1798ec28957772e180c8dea3fddf586481d (diff)
downloadponymap-0e51b3741185055d5bb82adc314d89a1c15b64ae.tar.gz
ponymap-0e51b3741185055d5bb82adc314d89a1c15b64ae.tar.xz
ponymap-0e51b3741185055d5bb82adc314d89a1c15b64ae.zip
Optimize and simplify the epoll poller
On my own machine (4096 max FD's), scanning localhost for all services, there was no change to speak of. On another one, though, with 65536 max FD's scanning localhost and another machine simultaneously for a specific service, there was a dramatic speedup allowing much faster scans, with userspace load dropping to about a quarter of a second. As a bonus, it makes the code simpler.
-rw-r--r--utils.c41
1 files changed, 14 insertions, 27 deletions
diff --git a/utils.c b/utils.c
index 2ab58d5..019fcdd 100644
--- a/utils.c
+++ b/utils.c
@@ -1063,11 +1063,7 @@ struct poller
struct poller_timers timers; ///< Timeouts
struct poller_idle *idle; ///< Idle events
- /// Index of the element in `revents' that's about to be dispatched next.
- int dispatch_next;
-
- /// The total number of entries stored in `revents' by epoll_wait().
- int dispatch_total;
+ int revents_len; ///< Number of entries in `revents'
};
static void
@@ -1081,11 +1077,9 @@ poller_init (struct poller *self)
self->alloc = POLLER_MIN_ALLOC;
self->fds = xcalloc (self->alloc, sizeof *self->fds);
self->revents = xcalloc (self->alloc, sizeof *self->revents);
+ self->revents_len = 0;
poller_timers_init (&self->timers);
-
- self->dispatch_next = 0;
- self->dispatch_total = 0;
}
static void
@@ -1174,18 +1168,13 @@ poller_compare_fds (const void *ax, const void *bx)
static void
poller_remove_from_dispatch (struct poller *self, const struct poller_fd *fd)
{
- if (!self->dispatch_total)
+ if (!self->revents_len)
return;
struct epoll_event key = { .data.ptr = (void *) fd }, *fd_event;
- if (!(fd_event = bsearch (&key, self->revents,
- self->dispatch_total, sizeof *self->revents, poller_compare_fds)))
- return;
-
- ssize_t i = fd_event - self->revents;
- if (i < self->dispatch_next)
- self->dispatch_next--;
- memmove (fd_event, fd_event + 1, (--self->dispatch_total - i) * sizeof key);
+ if ((fd_event = bsearch (&key, self->revents,
+ self->revents_len, sizeof *self->revents, poller_compare_fds)))
+ fd_event->events = -1;
}
static void
@@ -1211,7 +1200,7 @@ static void
poller_run (struct poller *self)
{
// Not reentrant
- hard_assert (!self->dispatch_total);
+ hard_assert (!self->revents_len);
int n_fds;
do
@@ -1222,31 +1211,29 @@ poller_run (struct poller *self)
if (n_fds == -1)
exit_fatal ("%s: %s", "epoll", strerror (errno));
- self->dispatch_next = 0;
- self->dispatch_total = n_fds;
-
// Sort them by file descriptor number for binary search
qsort (self->revents, n_fds, sizeof *self->revents, poller_compare_fds);
+ self->revents_len = n_fds;
poller_timers_dispatch (&self->timers);
poller_idle_dispatch (self->idle);
- while (self->dispatch_next < self->dispatch_total)
+ for (int i = 0; i < n_fds; i++)
{
- struct epoll_event *revents = self->revents + self->dispatch_next;
- struct poller_fd *fd = revents->data.ptr;
+ struct epoll_event *revents = self->revents + i;
+ if (revents->events == (uint32_t) -1)
+ continue;
+ struct poller_fd *fd = revents->data.ptr;
struct pollfd pfd;
pfd.fd = fd->fd;
pfd.revents = poller_epoll_to_poll_events (revents->events);
pfd.events = fd->events;
- self->dispatch_next++;
fd->dispatcher (&pfd, fd->user_data);
}
- self->dispatch_next = 0;
- self->dispatch_total = 0;
+ self->revents_len = 0;
}
#else // !__linux__