]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
OPTIM: ssl: implement dynamic record size adjustment
authorWilly Tarreau <w@1wt.eu>
Sun, 2 Feb 2014 01:00:24 +0000 (02:00 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 6 Feb 2014 10:37:29 +0000 (11:37 +0100)
By having the stream interface pass the CF_STREAMER flag to the
snd_buf() primitive, we're able to tell the send layer whether
we're sending large chunks or small ones.

We use this information in SSL to adjust the max record dynamically.
This results in small chunks respecting tune.ssl.maxrecord at the
beginning of a transfer or for small transfers, with an automatic
switch to full records if the exchanges last long. This allows the
receiver to parse HTML contents on the fly without having to retrieve
16kB of data, which is even more important with small initcwnd since
the receiver does not need to wait for round trips to start fetching
new objects. However, sending large files still produces large chunks.

For example, with tune.ssl.maxrecord = 2859, we see 5 write(2885)
sent in two segments each and 6 write(16421).

This idea was first proposed on the haproxy mailing list by Ilya Grigorik.

include/types/connection.h
src/ssl_sock.c
src/stream_interface.c

index f8e526ac4955bc65dbeb765cc4743e0d633f86e6..5341a86d6236cf33d1482610542ca6035377385b 100644 (file)
@@ -180,6 +180,7 @@ enum {
 /* flags that can be passed to xprt->snd_buf() */
 enum {
        CO_SFL_MSG_MORE    = 0x0001,    /* More data to come afterwards */
+       CO_SFL_STREAMER    = 0x0002,    /* Producer is continuously streaming data */
 };
 
 /* xprt_ops describes transport-layer operations for a connection. They
index 19505e5ee26b145e8b8d3fccb92038b9fa814e2e..5ac2b0653cc4931e50c9b0c7d1afd7612aa29b1d 100644 (file)
@@ -1528,7 +1528,8 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
        while (buf->o) {
                try = bo_contig_data(buf);
 
-               if (global.tune.ssl_max_record && try > global.tune.ssl_max_record)
+               if (!(flags & CO_SFL_STREAMER) &&
+                   global.tune.ssl_max_record && try > global.tune.ssl_max_record)
                        try = global.tune.ssl_max_record;
 
                ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
index 967f6451c59c3beffdc176ed49ca2baa34ecd6b9..b3364a3a91cb3be74e32fbcc2bd8959b6053d8a1 100644 (file)
@@ -701,6 +701,9 @@ static void si_conn_send(struct connection *conn)
                    ((chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) == CF_SHUTW_NOW))
                        send_flag |= CO_SFL_MSG_MORE;
 
+               if (chn->flags & CF_STREAMER)
+                       send_flag |= CO_SFL_STREAMER;
+
                ret = conn->xprt->snd_buf(conn, chn->buf, send_flag);
                if (ret > 0) {
                        chn->flags |= CF_WRITE_PARTIAL;