]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-h1: pass CO_RFL_READ_ONCE to the lower layers when relevant
authorWilly Tarreau <w@1wt.eu>
Thu, 20 Feb 2020 10:11:50 +0000 (11:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 21 Feb 2020 10:38:50 +0000 (11:38 +0100)
When we're in H1_MSG_RQBEFORE or H1_MSG_RPBEFORE, we know that the
first message is highly likely the only one and that it's pointless
to try to perform a second recvfrom() to complete a first partial
read. This is similar to what used to be done in the older I/O methods
with the CF_READ_DONTWAIT flag on the channel. So let's pass
CO_RFL_READ_ONCE to the transport layer during rcv_buf() in this case.

By doing so, in a test involving keep-alive connections with a non-null
client think time, we remove 20% of the recvfrom() calls, all of which
used to systematically fail. More precisely, we observe a drop from 5.0
recvfrom() per request with 60% failure to 4.0 per request with 50%
failure.

src/mux_h1.c

index f175ac9bce9c564111a75784b4d1685c4fee7da7..3128501c5682bc2662688d5328a57e14dac12ef8 100644 (file)
@@ -1986,6 +1986,7 @@ static int h1_recv(struct h1c *h1c)
        struct h1s *h1s = h1c->h1s;
        size_t ret = 0, max;
        int rcvd = 0;
+       int flags = 0;
 
        TRACE_ENTER(H1_EV_H1C_RECV, h1c->conn);
 
@@ -2021,6 +2022,10 @@ static int h1_recv(struct h1c *h1c)
        if (b_data(&h1c->ibuf) > 0 && b_data(&h1c->ibuf) < 128)
                b_slow_realign(&h1c->ibuf, trash.area, 0);
 
+       /* avoid useless reads after first responses */
+       if (h1s && (h1s->req.state == H1_MSG_RQBEFORE || h1s->res.state == H1_MSG_RPBEFORE))
+               flags |= CO_RFL_READ_ONCE;
+
        max = buf_room_for_htx_data(&h1c->ibuf);
        if (max) {
                if (h1c->flags & H1C_F_IN_FULL) {
@@ -2035,7 +2040,7 @@ static int h1_recv(struct h1c *h1c)
                         */
                        h1c->ibuf.head  = sizeof(struct htx);
                }
-               ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, &h1c->ibuf, max, 0);
+               ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, &h1c->ibuf, max, flags);
        }
        if (ret > 0) {
                TRACE_DATA("data received", H1_EV_H1C_RECV, h1c->conn,,, (size_t[]){ret});