]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: raw_sock: make sure to disable polling once everything is sent
authorWilly Tarreau <w@1wt.eu>
Wed, 8 Jan 2020 08:54:02 +0000 (09:54 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 8 Jan 2020 08:59:40 +0000 (09:59 +0100)
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

index 64f7a05d1e916a143fdf34888221643ffa942272..ed90a02dc70d8b3a5cecc5b81d8ba779c6588d86 100644 (file)
@@ -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 */