From: Willy Tarreau Date: Sun, 3 Jan 2010 10:37:54 +0000 (+0100) Subject: [OPTIM] http: set MSG_MORE on response when a pipelined request is pending X-Git-Tag: v1.4-dev5~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=face8392965c2bb93353ff31d16c15310ca499bf;p=thirdparty%2Fhaproxy.git [OPTIM] http: set MSG_MORE on response when a pipelined request is pending 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. --- diff --git a/include/types/buffers.h b/include/types/buffers.h index fd078fa8c7..34189cde0f 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -112,6 +112,7 @@ #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)) diff --git a/src/proto_http.c b/src/proto_http.c index d8dc7113ed..5cc0f23e02 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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) diff --git a/src/stream_sock.c b/src/stream_sock.c index 7e9dd2c2fc..4a9434c4f8 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -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 {