From 08fa16e397ffb1c6511b98ade2a3bfff9435e521 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 8 Jan 2020 09:54:02 +0100 Subject: [PATCH] MINOR: raw_sock: make sure to disable polling once everything is sent Analysing traces revealed a rare but surprizing pattern : connect() = -1 EAGAIN send() = success epoll_ctl(ADD, EPOLLOUT) epoll_wait() recvfrom() = success close() What happens is that the failed connect() creates an FD update for pollout, but the successful synchronous send() doesn't disable it because polling was only disabled in the FD handler. But a successful synchronous connect() cancellation is a good opportunity to disable polling before it's effectively enabled in the next loop, so better disable it when reaching the end. The cost is very low if it was already disabled anyway (one atomic op). This only affects local connections but with this the typical number of epoll_ctl() calls per connection dropped from ~4.2 to ~3.8 for plain TCP and 10k transfers. --- src/raw_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/raw_sock.c b/src/raw_sock.c index 64f7a05d1..ed90a02dc 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -378,6 +378,8 @@ static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const s /* if the system buffer is full, don't insist */ if (ret < try) break; + if (!count) + fd_stop_send(conn->handle.fd); } else if (ret == 0 || errno == EAGAIN || errno == ENOTCONN || errno == EINPROGRESS) { /* nothing written, we need to poll for write first */