]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[OPTIM] http: set MSG_MORE on response when a pipelined request is pending
authorWilly Tarreau <w@1wt.eu>
Sun, 3 Jan 2010 10:37:54 +0000 (11:37 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 3 Jan 2010 10:37:54 +0000 (11:37 +0100)
Many times we see a lot of short responses in HTTP (typically 304 on a
reload). It is a waste of network bandwidth to send that many small packets
when we know we can merge them. When we know that another HTTP request is
following a response, we set BF_EXPECT_MORE on the response buffer, which
will turn MSG_MORE on exactly once. That way, multiple short responses can
leave pipelined if their corresponding requests were also pipelined.

include/types/buffers.h
src/proto_http.c
src/stream_sock.c

index fd078fa8c73c7ccea87756fb1b4cc02c998d48ae..34189cde0fb4ac3bc2ef61c0ca5bbf7812fafbb0 100644 (file)
 #define BF_AUTO_CONNECT   0x800000  /* consumer may attempt to establish a new connection */
 
 #define BF_DONT_READ     0x1000000  /* disable reading for now */
+#define BF_EXPECT_MORE   0x2000000  /* more data expected to be sent very soon (one-shoot) */
 
 /* Use these masks to clear the flags before going back to lower layers */
 #define BF_CLEAR_READ     (~(BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_ATTACHED))
index d8dc7113ed652308292adf6cf0745cdb884e836b..5cc0f23e02cd653fc613611f3648f8def2a31448 100644 (file)
@@ -3497,6 +3497,13 @@ int http_request_forward_body(struct session *s, struct buffer *req, int an_bit)
                                if (s->be->options2 & PR_O2_INDEPSTR)
                                        s->req->cons->flags |= SI_FL_INDEP_STR;
 
+                               /* if the request buffer is not empty, it means we're
+                                * about to process another request, so send pending
+                                * data with MSG_MORE to merge TCP packets when possible.
+                                */
+                               if (s->req->l)
+                                       s->rep->flags |= BF_EXPECT_MORE;
+
                                /* make ->lr point to the first non-forwarded byte */
                                s->req->lr = s->req->w + s->req->send_max;
                                if (s->req->lr >= s->req->data + s->req->size)
index 7e9dd2c2fca6a61bda3b220aaa280d7003ef93a7..4a9434c4f8d19bed3ef7d0b151dc3087a3313473 100644 (file)
@@ -608,16 +608,20 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
                 * tests.
                 */
 
-               if (MSG_NOSIGNAL) {
+               if (MSG_NOSIGNAL && MSG_MORE) {
                        unsigned int send_flag = MSG_DONTWAIT | MSG_NOSIGNAL;
 
-                       if (MSG_MORE &&
-                           ((b->to_forward && b->to_forward != BUF_INFINITE_FORWARD) ||
+                       if (((b->to_forward && b->to_forward != BUF_INFINITE_FORWARD) ||
                             ((b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK)) == BF_SHUTW_NOW && (max == b->send_max)) ||
                             (max != b->l && max != b->send_max))
                            && (fdtab[si->fd].flags & FD_FL_TCP)) {
                                send_flag |= MSG_MORE;
                        }
+                       else if (b->flags & BF_EXPECT_MORE) {
+                               /* it was forced on the buffer, this flag is one-shoot */
+                               b->flags &= ~BF_EXPECT_MORE;
+                               send_flag |= MSG_MORE;
+                       }
 
                        ret = send(si->fd, b->w, max, send_flag);
                } else {