]> granicus.if.org Git - apache/commitdiff
mod_buffer: Optimise the buffering of heap buckets when the heap
authorGraham Leggett <minfrin@apache.org>
Sun, 16 Nov 2008 22:23:25 +0000 (22:23 +0000)
committerGraham Leggett <minfrin@apache.org>
Sun, 16 Nov 2008 22:23:25 +0000 (22:23 +0000)
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
modules/filters/mod_buffer.c

diff --git a/CHANGES b/CHANGES
index a38639bebd72943ffcec9a1c36d03a1fb4285c62..be59cd1daec8afea727e2108b8cdbeb1f82ff3c8 100644 (file)
--- 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
index c8e3bf38e21b6f620fd3c174d3284b8879a057bb..08a800f3e280f389193a55fef3c40d2b107ec2b9 100644 (file)
@@ -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;