Hi,

there is still the problem that during a request, many bucket brigades 
being created which are only cleaned up after the request is 
finished, see 
http://issues.apache.org/bugzilla/show_bug.cgi?id=23567 . There was 
some discussion about retaining ownership of a brigade when 
ap_pass_brigade() is called, and then reusing the brigades [1]. But 
this does not seem to be implemented in 2.2, yet.

But I found two locations where the creation of a new brigade could be 
avoided:

- In buffer_output()/ap_old_write_filter(), it is possible to keep the 
brigade around and reuse it after the next flush.

- In ap_http_chunk_filter(), a new brigade is created for every flush 
bucket. But it is not really necessary if the flush bucket is the 
last bucket in the brigade.

I don't know yet whether the saving is significant in practice. But it
saves two brigades on every combination of ap_rwrite()/ap_rflush()  
and mod_php uses ap_r*() quite a lot.

A patch is attached. It's against 2.2.6 but applies to trunk.

Cheers,
Stefan

[1] 
http://mail-archives.apache.org/mod_mbox/httpd-dev/200504.mbox/<9b5d906c83b6650b9512eb9e7ac96be1%40ricilake.net>
diff -urNad trunk~/modules/http/chunk_filter.c trunk/modules/http/chunk_filter.c
--- trunk~/modules/http/chunk_filter.c	2006-07-12 05:38:44.000000000 +0200
+++ trunk/modules/http/chunk_filter.c	2007-12-02 18:52:20.955996723 +0100
@@ -85,7 +85,9 @@
             }
             if (APR_BUCKET_IS_FLUSH(e)) {
                 flush = e;
-                more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
+                if (e != APR_BRIGADE_LAST(b)) {
+                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
+                }
                 break;
             }
             else if (e->length == (apr_size_t)-1) {
diff -urNad trunk~/server/protocol.c trunk/server/protocol.c
--- trunk~/server/protocol.c	2006-07-12 05:38:44.000000000 +0200
+++ trunk/server/protocol.c	2007-12-02 18:51:19.200477476 +0100
@@ -1385,6 +1385,7 @@
 
 typedef struct {
     apr_bucket_brigade *bb;
+    apr_bucket_brigade *tmpbb;
 } old_write_filter_ctx;
 
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
@@ -1399,8 +1400,7 @@
          * can simply insert our buffered data at the front and
          * pass the whole bundle down the chain.
          */
-        APR_BRIGADE_CONCAT(ctx->bb, bb);
-        bb = ctx->bb;
+        APR_BRIGADE_PREPEND(bb, ctx->bb);
         ctx->bb = NULL;
     }
 
@@ -1449,7 +1449,12 @@
     ctx = r->output_filters->ctx;
 
     if (ctx->bb == NULL) {
-        ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
+        if (ctx->tmpbb == NULL) {
+            ctx->tmpbb = ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
+	}
+	else {
+	    ctx->bb = ctx->tmpbb;
+	}
     }
 
     return ap_fwrite(f->next, ctx->bb, str, len);

Reply via email to