You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by sf...@apache.org on 2009/10/04 09:37:28 UTC

svn commit: r821471 - in /httpd/httpd/trunk: CHANGES modules/filters/mod_deflate.c modules/filters/mod_sed.c modules/http/chunk_filter.c server/protocol.c

Author: sf
Date: Sun Oct  4 07:37:28 2009
New Revision: 821471

URL: http://svn.apache.org/viewvc?rev=821471&view=rev
Log:
core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket
brigades in several places

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/filters/mod_deflate.c
    httpd/httpd/trunk/modules/filters/mod_sed.c
    httpd/httpd/trunk/modules/http/chunk_filter.c
    httpd/httpd/trunk/server/protocol.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=821471&r1=821470&r2=821471&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Sun Oct  4 07:37:28 2009
@@ -10,6 +10,9 @@
      mod_proxy_ftp: NULL pointer dereference on error paths.
      [Stefan Fritsch <sf fritsch.de>, Joe Orton]
 
+  *) core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket
+     brigades in several places. [Stefan Fritsch]
+
   *) mod_cache: Fix uri_meets_conditions() so that CacheEnable will
      match by scheme, or by a wildcarded hostname. PR 40169
      [Ryan Pendergast <rpender us.ibm.com>, Graham Leggett]

Modified: httpd/httpd/trunk/modules/filters/mod_deflate.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_deflate.c?rev=821471&r1=821470&r2=821471&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/filters/mod_deflate.c (original)
+++ httpd/httpd/trunk/modules/filters/mod_deflate.c Sun Oct  4 07:37:28 2009
@@ -1011,14 +1011,11 @@
     }
 
     if (!APR_BRIGADE_EMPTY(ctx->proc_bb)) {
-        apr_bucket_brigade *newbb;
-
         /* May return APR_INCOMPLETE which is fine by us. */
         apr_brigade_partition(ctx->proc_bb, readbytes, &bkt);
 
-        newbb = apr_brigade_split(ctx->proc_bb, bkt);
         APR_BRIGADE_CONCAT(bb, ctx->proc_bb);
-        APR_BRIGADE_CONCAT(ctx->proc_bb, newbb);
+        apr_brigade_split_ex(bb, bkt, ctx->proc_bb);
     }
 
     return APR_SUCCESS;

Modified: httpd/httpd/trunk/modules/filters/mod_sed.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_sed.c?rev=821471&r1=821470&r2=821471&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/filters/mod_sed.c (original)
+++ httpd/httpd/trunk/modules/filters/mod_sed.c Sun Oct  4 07:37:28 2009
@@ -48,6 +48,7 @@
     ap_filter_t *f;
     request_rec *r;
     apr_bucket_brigade *bb;
+    apr_bucket_brigade *bbinp;
     char *outbuf;
     char *curoutbuf;
     int bufsize;
@@ -392,6 +393,7 @@
                                            &sed_module);
     sed_filter_ctxt *ctx = f->ctx;
     apr_status_t status;
+    apr_bucket_brigade *bbinp;
     sed_expr_config *sed_cfg = &cfg->input;
 
     if (mode != AP_MODE_READBYTES) {
@@ -413,9 +415,12 @@
         if (status != APR_SUCCESS)
              return status;
         ctx = f->ctx;
-        ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+        ctx->bb    = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+        ctx->bbinp = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
     }
 
+    bbinp = ctx->bbinp;
+
     /* Here is the logic :
      * Read the readbytes data from next level fiter into bbinp. Loop through
      * the buckets in bbinp and read the data from buckets and invoke
@@ -435,11 +440,10 @@
      * the question is where to add it?
      */
     while (APR_BRIGADE_EMPTY(ctx->bb)) {
-        apr_bucket_brigade *bbinp;
         apr_bucket *b;
 
         /* read the bytes from next level filter */
-        bbinp = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+        apr_brigade_cleanup(bbinp);
         status = ap_get_brigade(f->next, bbinp, mode, block, readbytes);
         if (status != APR_SUCCESS) {
             return status;
@@ -469,20 +473,16 @@
                 flush_output_buffer(ctx);
             }
         }
-        apr_brigade_cleanup(bbinp);
-        apr_brigade_destroy(bbinp);
     }
 
     if (!APR_BRIGADE_EMPTY(ctx->bb)) {
-        apr_bucket_brigade *newbb = NULL;
         apr_bucket *b = NULL;
 
         /* This may return APR_INCOMPLETE which should be fine */
         apr_brigade_partition(ctx->bb, readbytes, &b);
 
-        newbb = apr_brigade_split(ctx->bb, b);
         APR_BRIGADE_CONCAT(bb, ctx->bb);
-        APR_BRIGADE_CONCAT(ctx->bb, newbb);
+        apr_brigade_split_ex(bb, b, ctx->bb);
     }
     return APR_SUCCESS;
 }

Modified: httpd/httpd/trunk/modules/http/chunk_filter.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http/chunk_filter.c?rev=821471&r1=821470&r2=821471&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/chunk_filter.c (original)
+++ httpd/httpd/trunk/modules/http/chunk_filter.c Sun Oct  4 07:37:28 2009
@@ -49,11 +49,11 @@
 #define ASCII_CRLF  "\015\012"
 #define ASCII_ZERO  "\060"
     conn_rec *c = f->r->connection;
-    apr_bucket_brigade *more;
+    apr_bucket_brigade *more, *tmp;
     apr_bucket *e;
     apr_status_t rv;
 
-    for (more = NULL; b; b = more, more = NULL) {
+    for (more = tmp = NULL; b; b = more, more = NULL) {
         apr_off_t bytes = 0;
         apr_bucket *eos = NULL;
         apr_bucket *flush = NULL;
@@ -85,7 +85,7 @@
             if (APR_BUCKET_IS_FLUSH(e)) {
                 flush = e;
                 if (e != APR_BRIGADE_LAST(b)) {
-                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
+                    more = apr_brigade_split_ex(b, APR_BUCKET_NEXT(e), tmp);
                 }
                 break;
             }
@@ -105,7 +105,7 @@
                      * block so we pass down what we have so far.
                      */
                     bytes += len;
-                    more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
+                    more = apr_brigade_split_ex(b, APR_BUCKET_NEXT(e), tmp);
                     break;
                 }
                 else {
@@ -189,6 +189,8 @@
         if (rv != APR_SUCCESS || eos != NULL) {
             return rv;
         }
+        tmp = b;
+        apr_brigade_cleanup(tmp);
     }
     return APR_SUCCESS;
 }

Modified: httpd/httpd/trunk/server/protocol.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/protocol.c?rev=821471&r1=821470&r2=821471&view=diff
==============================================================================
--- httpd/httpd/trunk/server/protocol.c (original)
+++ httpd/httpd/trunk/server/protocol.c Sun Oct  4 07:37:28 2009
@@ -1251,6 +1251,7 @@
                      * least one bucket on to the next output filter
                      * for this request
                      */
+    apr_bucket_brigade *tmpbb;
 };
 
 /* This filter computes the content length, but it also computes the number
@@ -1271,6 +1272,7 @@
     if (!ctx) {
         f->ctx = ctx = apr_palloc(r->pool, sizeof(*ctx));
         ctx->data_sent = 0;
+        ctx->tmpbb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
     }
 
     /* Loop through this set of buckets to compute their length
@@ -1300,16 +1302,15 @@
                  * do a blocking read on the next batch.
                  */
                 if (e != APR_BRIGADE_FIRST(b)) {
-                    apr_bucket_brigade *split = apr_brigade_split(b, e);
+                    apr_brigade_split_ex(b, e, ctx->tmpbb);
                     apr_bucket *flush = apr_bucket_flush_create(r->connection->bucket_alloc);
 
                     APR_BRIGADE_INSERT_TAIL(b, flush);
                     rv = ap_pass_brigade(f->next, b);
                     if (rv != APR_SUCCESS || f->c->aborted) {
-                        apr_brigade_destroy(split);
                         return rv;
                     }
-                    b = split;
+                    APR_BRIGADE_CONCAT(b, ctx->tmpbb);
                     e = APR_BRIGADE_FIRST(b);
 
                     ctx->data_sent = 1;
@@ -1402,6 +1403,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(
@@ -1422,16 +1424,11 @@
     return ap_pass_brigade(f->next, bb);
 }
 
-static apr_status_t buffer_output(request_rec *r,
-                                  const char *str, apr_size_t len)
+static ap_filter_t *insert_old_write_filter(request_rec *r)
 {
-    conn_rec *c = r->connection;
     ap_filter_t *f;
     old_write_filter_ctx *ctx;
 
-    if (len == 0)
-        return APR_SUCCESS;
-
     /* future optimization: record some flags in the request_rec to
      * say whether we've added our filter, and whether it is first.
      */
@@ -1445,24 +1442,41 @@
     if (f == NULL) {
         /* our filter hasn't been added yet */
         ctx = apr_pcalloc(r->pool, sizeof(*ctx));
+        ctx->tmpbb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
         ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);
         f = r->output_filters;
     }
 
+    return f;
+}
+
+static apr_status_t buffer_output(request_rec *r,
+                                  const char *str, apr_size_t len)
+{
+    conn_rec *c = r->connection;
+    ap_filter_t *f;
+    old_write_filter_ctx *ctx;
+
+    if (len == 0)
+        return APR_SUCCESS;
+
+    f = insert_old_write_filter(r);
+    ctx = f->ctx;
+
     /* if the first filter is not our buffering filter, then we have to
      * deliver the content through the normal filter chain
      */
     if (f != r->output_filters) {
-        apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
+        apr_status_t rv;
         apr_bucket *b = apr_bucket_transient_create(str, len, c->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(bb, b);
+        APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b);
 
-        return ap_pass_brigade(r->output_filters, bb);
+        rv = ap_pass_brigade(r->output_filters, ctx->tmpbb);
+        apr_brigade_cleanup(ctx->tmpbb);
+        return rv;
     }
 
-    /* grab the context from our filter */
-    ctx = r->output_filters->ctx;
-
     if (ctx->bb == NULL) {
         ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
     }
@@ -1617,13 +1631,20 @@
 AP_DECLARE(int) ap_rflush(request_rec *r)
 {
     conn_rec *c = r->connection;
-    apr_bucket_brigade *bb;
     apr_bucket *b;
+    ap_filter_t *f;
+    old_write_filter_ctx *ctx;
+    apr_status_t rv;
+
+    f = insert_old_write_filter(r);
+    ctx = f->ctx;
 
-    bb = apr_brigade_create(r->pool, c->bucket_alloc);
     b = apr_bucket_flush_create(c->bucket_alloc);
-    APR_BRIGADE_INSERT_TAIL(bb, b);
-    if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)
+    APR_BRIGADE_INSERT_TAIL(ctx->tmpbb, b);
+
+    rv = ap_pass_brigade(r->output_filters, ctx->tmpbb);
+    apr_brigade_cleanup(ctx->tmpbb);
+    if (rv != APR_SUCCESS)
         return -1;
 
     return 0;



Re: svn commit: r821471 - in /httpd/httpd/trunk: CHANGES modules/filters/mod_deflate.c modules/filters/mod_sed.c modules/http/chunk_filter.c server/protocol.c

Posted by Stefan Fritsch <sf...@sfritsch.de>.
On Sunday 04 October 2009, Ruediger Pluem wrote:
> To be on the safe side we should do apr_brigade_cleanup(b) here.
> 
Thanks. Fixed in r821481


Re: svn commit: r821471 - in /httpd/httpd/trunk: CHANGES modules/filters/mod_deflate.c modules/filters/mod_sed.c modules/http/chunk_filter.c server/protocol.c

Posted by Ruediger Pluem <rp...@apache.org>.

On 10/04/2009 09:37 AM, sf@apache.org wrote:
> Author: sf
> Date: Sun Oct  4 07:37:28 2009
> New Revision: 821471
> 
> URL: http://svn.apache.org/viewvc?rev=821471&view=rev
> Log:
> core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket
> brigades in several places
> 
> Modified:
>     httpd/httpd/trunk/CHANGES
>     httpd/httpd/trunk/modules/filters/mod_deflate.c
>     httpd/httpd/trunk/modules/filters/mod_sed.c
>     httpd/httpd/trunk/modules/http/chunk_filter.c
>     httpd/httpd/trunk/server/protocol.c
> 


> Modified: httpd/httpd/trunk/server/protocol.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/protocol.c?rev=821471&r1=821470&r2=821471&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/server/protocol.c (original)
> +++ httpd/httpd/trunk/server/protocol.c Sun Oct  4 07:37:28 2009

> @@ -1300,16 +1302,15 @@
>                   * do a blocking read on the next batch.
>                   */
>                  if (e != APR_BRIGADE_FIRST(b)) {
> -                    apr_bucket_brigade *split = apr_brigade_split(b, e);
> +                    apr_brigade_split_ex(b, e, ctx->tmpbb);
>                      apr_bucket *flush = apr_bucket_flush_create(r->connection->bucket_alloc);
>  
>                      APR_BRIGADE_INSERT_TAIL(b, flush);
>                      rv = ap_pass_brigade(f->next, b);
>                      if (rv != APR_SUCCESS || f->c->aborted) {
> -                        apr_brigade_destroy(split);
>                          return rv;
>                      }
> -                    b = split;


To be on the safe side we should do apr_brigade_cleanup(b) here.

> +                    APR_BRIGADE_CONCAT(b, ctx->tmpbb);
>                      e = APR_BRIGADE_FIRST(b);
>  
>                      ctx->data_sent = 1;

Regards

RĂ¼diger