From 5b28da886ca24fb6bd4ff6f3ae6edd4d5978924d Mon Sep 17 00:00:00 2001 From: Graham Leggett Date: Sun, 16 Nov 2008 22:23:25 +0000 Subject: [PATCH] mod_buffer: Optimise the buffering of heap buckets when the heap buckets stay exactly APR_BUCKET_BUFF_SIZE long. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@718125 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 4 ++++ modules/filters/mod_buffer.c | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index a38639bebd..be59cd1dae 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.3.0 [ When backported to 2.2.x, remove entry from this file ] + *) mod_buffer: Optimise the buffering of heap buckets when the heap + buckets stay exactly APR_BUCKET_BUFF_SIZE long. [Graham Leggett, + Ruediger Pluem] + *) mod_buffer: Optional support for buffering of the input and output filter stacks. Can collapse many small buckets into fewer larger buckets, and prevents excessively small chunks being sent over diff --git a/modules/filters/mod_buffer.c b/modules/filters/mod_buffer.c index c8e3bf38e2..08a800f3e2 100644 --- a/modules/filters/mod_buffer.c +++ b/modules/filters/mod_buffer.c @@ -57,6 +57,7 @@ static apr_status_t buffer_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) { request_rec *r = f->r; buffer_ctx *ctx = f->ctx; apr_status_t rv = APR_SUCCESS; + int move = 0; /* first time in? create a context */ if (!ctx) { @@ -81,6 +82,11 @@ static apr_status_t buffer_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) { return ap_pass_brigade(f->next, bb); } + /* Empty buffer means we can potentially optimise below */ + if (APR_BRIGADE_EMPTY(ctx->bb)) { + move = 1; + } + while (APR_SUCCESS == rv && !APR_BRIGADE_EMPTY(bb)) { const char *data; apr_off_t len; @@ -146,10 +152,26 @@ static apr_status_t buffer_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) { */ if (APR_SUCCESS == (rv = apr_bucket_read(e, &data, &size, APR_BLOCK_READ))) { - apr_brigade_write(ctx->bb, NULL, NULL, data, size); + + /* further optimisation: if the buckets are already heap + * buckets, and the buckets stay exactly APR_BUCKET_BUFF_SIZE + * long (as they would be if we were reading bits of a + * large bucket), then move the buckets instead of copying + * them. + */ + if (move && APR_BUCKET_IS_HEAP(e)) { + APR_BUCKET_REMOVE(e); + APR_BRIGADE_INSERT_TAIL(ctx->bb, e); + if (APR_BUCKET_BUFF_SIZE != size) { + move = 0; + } + } else { + apr_brigade_write(ctx->bb, NULL, NULL, data, size); + apr_bucket_delete(e); + } + } - apr_bucket_delete(e); } return rv; -- 2.40.0