From 20775c848738957ef3fa98c043d87a72c5e85bf3 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 8 Dec 2014 18:16:25 +0100 Subject: EXP: httpterm: implement zero-copy to send the output data When possible, prepare a buffer to pass data to the channel so that we can avoid a painful memory copy. Most of the time the output buffer is empty so we can simply swap the buffers. --- src/proto_http.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index 186ea54..db17e2c 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3185,6 +3185,7 @@ struct hterm_ctx { }; static struct chunk hterm_chunk; +static struct buffer *hterm_buf; static int httpterm_send_http_headers(struct stream_interface *si) { @@ -3293,6 +3294,7 @@ static void httpterm_io_handler(struct stream_interface *si) } if (appctx->st0 == HT_RES_BODY) { + struct buffer *swp; int max; int offset; @@ -3327,8 +3329,20 @@ static void httpterm_io_handler(struct stream_interface *si) tmp_chunk.str = hterm_chunk.str + offset; tmp_chunk.len = max; - if (bi_putchk(si->ib, &tmp_chunk) == -1) - goto fail; + + /* Note that we cannot use hterm_chunk.str + offset below as we'd corrupt the buffer */ + hterm_buf->p = hterm_buf->data; + hterm_buf->i = max; + hterm_buf->o = 0; + + swp = bi_swpbuf(si->ib, hterm_buf); + if (!swp || swp == hterm_buf) { + /* zero copy failed */ + if (bi_putchk(si->ib, &tmp_chunk) == -1) + goto fail; + } + else + hterm_buf = swp; hctx->req_size -= max; } while (hctx->req_chunked && max); /* this guarantees we write the final chunk */ @@ -3409,11 +3423,12 @@ int http_handle_httpterm(struct session *s, struct channel *req) unsigned int mult, result; /* allocate and initialize the stuf we want to return */ - if (unlikely(!hterm_chunk.size)) { + if (unlikely(!hterm_buf)) { int index; - chunk_init(&hterm_chunk, malloc(global.tune.bufsize), global.tune.bufsize); - for (index = 0; index < global.tune.bufsize; index++) + b_alloc(&hterm_buf); + chunk_init(&hterm_chunk, hterm_buf->data, hterm_buf->size); + for (index = 0; index < hterm_buf->size; index++) hterm_chunk.str[index] = ".123456789"[index % 10]; hterm_chunk.len = hterm_chunk.size; } -- 1.7.12.1