Commit d217d1a1 authored by Graham Leggett's avatar Graham Leggett
Browse files

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
parent 27bff06d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+24 −2
Original line number Diff line number Diff line
@@ -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))) {

            /* 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;