From: Stefan Fritsch Date: Sun, 4 Oct 2009 07:37:28 +0000 (+0000) Subject: core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket X-Git-Tag: 2.3.3~220 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fbdde88b36bc806e4f79113f6d171d170af27849;p=apache core, mod_deflate, mod_sed: Reduce memory usage by reusing bucket brigades in several places git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@821471 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index fd5bb5b176..38c3f92a1a 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,9 @@ Changes with Apache 2.3.3 mod_proxy_ftp: NULL pointer dereference on error paths. [Stefan Fritsch , 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 , Graham Leggett] diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c index 4451d77a20..2cbbf6bbf6 100644 --- a/modules/filters/mod_deflate.c +++ b/modules/filters/mod_deflate.c @@ -1011,14 +1011,11 @@ static apr_status_t deflate_in_filter(ap_filter_t *f, } 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; diff --git a/modules/filters/mod_sed.c b/modules/filters/mod_sed.c index 1fc72b0579..8c01fe1a0d 100644 --- a/modules/filters/mod_sed.c +++ b/modules/filters/mod_sed.c @@ -48,6 +48,7 @@ typedef struct sed_filter_ctxt 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 @@ static apr_status_t sed_request_filter(ap_filter_t *f, &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 @@ static apr_status_t sed_request_filter(ap_filter_t *f, 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 @@ static apr_status_t sed_request_filter(ap_filter_t *f, * 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 @@ static apr_status_t sed_request_filter(ap_filter_t *f, 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; } diff --git a/modules/http/chunk_filter.c b/modules/http/chunk_filter.c index a8ce0d0240..17fbabdb0a 100644 --- a/modules/http/chunk_filter.c +++ b/modules/http/chunk_filter.c @@ -49,11 +49,11 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) #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 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) 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 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) * 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 @@ apr_status_t ap_http_chunk_filter(ap_filter_t *f, apr_bucket_brigade *b) if (rv != APR_SUCCESS || eos != NULL) { return rv; } + tmp = b; + apr_brigade_cleanup(tmp); } return APR_SUCCESS; } diff --git a/server/protocol.c b/server/protocol.c index e082de9390..85965d08bc 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -1251,6 +1251,7 @@ struct content_length_ctx { * 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 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter( 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 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter( * 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 @@ AP_DECLARE(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset, 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 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter( 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 @@ static apr_status_t buffer_output(request_rec *r, 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_NONSTD(int) ap_rvputs(request_rec *r, ...) 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;