[Openvpn-devel,v3] multi_io: avoid redundant event_ctl() calls in multi_io_wait()
Commit Message
From: Gianmarco De Gregori <gianmarco@mandelbit.com>
multi_io_wait() registered each server UDP socket through
multi_io_process_flags(), which calls socket_set() without a persistent
cache and tun_set() once more for every UDP socket, also without a
cache. Both ended up in an event_ctl() on every loop iteration even
though nothing changed.
Now that the UDP sockets and the tun device are only ever armed for
reading, set them directly with EVENT_READ, caching the UDP socket
rwflags in the new link_socket.rwflags_persistent and the tun ones in
multi_io->tun_rwflags.
On a server with two UDP and one TCP listener this removes the
remaining epoll_ctl() calls from the loop (syscalls per received
packet 4.64 -> 3.36, UDP only 5.29 -> 3.77); at saturation the
server delivers 2-7% more traffic with UDP and uses 4-13% less CPU
at a fixed load.
With --enable-async-push the inotify descriptor was also registered on
every iteration; register it once (1504 -> 12 epoll_ctl() with
deferred auth).
Change-Id: I4379a167419d464c000dca3c5c032aaebb6dac73
Signed-off-by: Gianmarco De Gregori <gianmarco@mandelbit.com>
Acked-by: Razvan Cojocaru <razvanc@mailbox.org>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2050
---
This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to master.
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2050
This mail reflects revision 3 of this Change.
Acked-by according to Gerrit (reflected above):
Razvan Cojocaru <razvanc@mailbox.org>
@@ -73,8 +73,7 @@
* Evaluates the current I/O state (`flags`) and context mode to determine
* which READ or WRITE events to register in the event loop.
*
- * @note This function gets called from client instances from @c io_wait()
- * and from p2mp (Point-to-multipoint) instances in @c multi_io_wait().
+ * @note This function gets called from @c io_wait().
*
* @param c Pointer to the core context.
* @param es The event set where descriptors are registered.
@@ -136,7 +136,6 @@
multi_io_wait(struct multi_context *m)
{
int status;
- unsigned int *persistent = &m->multi_io->tun_rwflags;
for (int i = 0; i < m->top.c1.link_sockets_num; i++)
{
@@ -144,7 +143,7 @@
if (proto_is_dgram(sock->info.proto))
{
- multi_io_process_flags(&m->top, m->multi_io->es, sock, IOW_READ | IOW_WAIT_SIGNAL);
+ socket_set(sock, m->multi_io->es, EVENT_READ, &sock->ev_arg, &sock->rwflags_persistent);
}
else if (!tuntap_is_dco_win(m->top.c1.tuntap))
{
@@ -152,7 +151,7 @@
}
}
- tun_set(m->top.c1.tuntap, m->multi_io->es, EVENT_READ, MULTI_IO_TUN, persistent);
+ tun_set(m->top.c1.tuntap, m->multi_io->es, EVENT_READ, MULTI_IO_TUN, &m->multi_io->tun_rwflags);
#if defined(ENABLE_DCO)
dco_event_set(&m->top.c1.tuntap->dco, m->multi_io->es, MULTI_IO_DCO);
#endif
@@ -167,7 +166,11 @@
#ifdef ENABLE_ASYNC_PUSH
/* arm inotify watcher */
- event_ctl(m->multi_io->es, m->top.c2.inotify_fd, EVENT_READ, MULTI_IO_FILE_CLOSE_WRITE);
+ if (!m->multi_io->inotify_set)
+ {
+ event_ctl(m->multi_io->es, m->top.c2.inotify_fd, EVENT_READ, MULTI_IO_FILE_CLOSE_WRITE);
+ m->multi_io->inotify_set = true;
+ }
#endif
status =
@@ -55,6 +55,7 @@
int n_esr;
int maxevents;
unsigned int tun_rwflags;
+ bool inotify_set;
#ifdef ENABLE_MANAGEMENT
unsigned int management_persist_flags;
#endif
@@ -177,6 +177,9 @@
/* used for long-term queueing of pre-accepted socket listen */
bool listen_persistent_queued;
+ /* last rwflags set on the shared server-side UDP socket */
+ unsigned int rwflags_persistent;
+
const char *remote_host;
const char *remote_port;
const char *local_host;