httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Stoddard" <b...@wstoddard.com>
Subject Re: [PATCH] ap_r* efficiency improvements
Date Tue, 14 Nov 2000 20:32:29 GMT
It is more efficient to simply malloc your buffer and create a heap bucket out
of it instead of creating the transient bucket. The reason is that the
transient bucket will likely be converted to a heap bucket anyway in the
core_output_filter. When we implement a heap bucket pool, we will eliminate
the malloc as well.

Bill

----- Original Message -----
From: Victor J. Orlikowski <v.j.orlikowski@gte.net>
To: <new-httpd@apache.org>
Sent: Tuesday, November 14, 2000 3:06 PM
Subject: [PATCH] ap_r* efficiency improvements


> The following patch uses a buffer in the request_rec to buffer data
> coming into the ap_r* functions, instead of simply making a brigade +
> bucket each time any one of them is called. The idea is to 1) minimize
> the number of buckets and brigades created, and 2) increase the size
> of the buckets being created, so as to decrease overhead. This patch
> is somewhat dirty, so any comments to clean it up would be greatly
> appeciated.
> Measurements with ab show a fairly large improvement with this patch
> (esp. when testing mod_autoindex), but YMMV.
> Personally, even if a coalesce filter is still used, this is needed to
> decrease the number of buckets/brigades being shoved down the filter
> chain.
>
> Index: src/include/httpd.h
> ===================================================================
> RCS file: /cvs/apache/apache-2.0/src/include/httpd.h,v
> retrieving revision 1.116
> diff -u -d -b -r1.116 httpd.h
> --- httpd.h 2000/11/10 00:58:25 1.116
> +++ httpd.h 2000/11/14 19:58:13
> @@ -811,6 +811,18 @@
>      /** A flag to determine if the eos bucket has been sent yet
>       *  @defvar int eos_sent */
>      int eos_sent;
> +    /** A buffer to hold data to be coalesced into a reasonable size bucket
> +     *  @defvar char *coalesce_buf */
> +    char *coalesce_buf;
> +    /** A pointer to the current position in coalesce_buf
> +     *  @defvar char *coalesce_buf_cur */
> +    char *coalesce_buf_cur;
> +    /** Space used in coalesce_buf
> +     * @defvar apr_size_t coalesce_cnt */
> +    apr_size_t coalesce_cnt;
> +    /** Space remaining in coalesce_buf
> +     * @defvar apr_size_t coalesce_avail */
> +    apr_size_t coalesce_avail;
>
>  /* Things placed at the end of the record to avoid breaking binary
>   * compatibility.  It would be nice to remember to reorder the entire
> Index: src/main/http_protocol.c
> ===================================================================
> RCS file: /cvs/apache/apache-2.0/src/main/http_protocol.c,v
> retrieving revision 1.245
> diff -u -d -b -r1.245 http_protocol.c
> --- http_protocol.c 2000/11/14 06:41:37 1.245
> +++ http_protocol.c 2000/11/14 19:58:15
> @@ -1412,6 +1412,10 @@
>      r->the_request     = NULL;
>      r->output_filters  = conn->output_filters;
>      r->input_filters   = conn->input_filters;
> +    r->coalesce_buf    = apr_pcalloc(r->pool, MAX_STRING_LEN);
> +    r->coalesce_buf_cur = r->coalesce_buf;
> +    r->coalesce_cnt    = 0;
> +    r->coalesce_avail  = MAX_STRING_LEN;
>
>      apr_setsocketopt(conn->client_socket, APR_SO_TIMEOUT,
>                       conn->keptalive
> @@ -2566,6 +2570,7 @@
>          r = r->next;
>      }
>      /* tell the filter chain there is no more content coming */
> +    ap_rflush(r);
>      if (!r->eos_sent) {
>          end_output_stream(r);
>      }
> @@ -2897,29 +2902,70 @@
>  }
>  #endif /* AP_USE_MMAP_FILES */
>
> +#define RMIN_BUCKET_SIZE 4096
> +static void coalesce_buf_create_bucket(request_rec *r, ap_bucket_brigade
*bb)
> +{
> +    ap_bucket *b = ap_bucket_create_transient(r->coalesce_buf,
r->coalesce_cnt);
> +    AP_BRIGADE_INSERT_TAIL(bb, b);
> +    r->coalesce_buf_cur = r->coalesce_buf;
> +    r->coalesce_cnt = 0;
> +    r->coalesce_avail = MAX_STRING_LEN;
> +}
> +
> +static void coalesce_buf_insertc(request_rec *r, char c)
> +{
> +    *r->coalesce_buf_cur = c;
> +    r->coalesce_buf_cur++;
> +    r->coalesce_cnt++;
> +    r->coalesce_avail--;
> +}
> +
> +static void coalesce_buf_insertb(request_rec *r, ap_bucket_brigade *bb,
> +                                 const void *buf, int len)
> +{
> +    ap_bucket *b;
> +
> +    if (len < RMIN_BUCKET_SIZE) {
> +        if (len > r->coalesce_avail) {
> +            bb = ap_brigade_create(r->pool);
> +            coalesce_buf_create_bucket(r, bb);
> +        }
> +        memcpy(r->coalesce_buf_cur, buf, len);
> +        r->coalesce_cnt += len;
> +        r->coalesce_buf_cur += len;
> +        r->coalesce_avail -= len;
> +    }
> +    else {
> +        bb = ap_brigade_create(r->pool);
> +        coalesce_buf_create_bucket(r, bb);
> +        b = ap_bucket_create_transient(buf, len);
> +        AP_BRIGADE_INSERT_TAIL(bb, b);
> +    }
> +}
> +
>  AP_DECLARE(int) ap_rputc(int c, request_rec *r)
>  {
>      ap_bucket_brigade *bb = NULL;
> -    ap_bucket *b;
>      char c2 = (char)c;
>
>      if (r->connection->aborted) {
>   return EOF;
>      }
>
> +    if (r->coalesce_avail == 0) {
>      bb = ap_brigade_create(r->pool);
> -    b = ap_bucket_create_transient(&c2, 1);
> -    AP_BRIGADE_INSERT_TAIL(bb, b);
> +        coalesce_buf_create_bucket(r, bb);
>      ap_pass_brigade(r->output_filters, bb);
> +    }
>
> +    coalesce_buf_insertc(r, c2);
>      return c;
>  }
>
>  AP_DECLARE(int) ap_rputs(const char *str, request_rec *r)
>  {
>      ap_bucket_brigade *bb = NULL;
> -    ap_bucket *b;
> -    apr_size_t len;
> +    int len;
>
>      if (r->connection->aborted)
>          return EOF;
> @@ -2927,9 +2973,9 @@
>          return 0;
>
>      len = strlen(str);
> -    bb = ap_brigade_create(r->pool);
> -    b = ap_bucket_create_transient(str, len);
> -    AP_BRIGADE_INSERT_TAIL(bb, b);
> +
> +    coalesce_buf_insertb(r, bb, str, len);
> +    if (bb)
>      ap_pass_brigade(r->output_filters, bb);
>
>      return len;
> @@ -2938,17 +2984,16 @@
>  AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r)
>  {
>      ap_bucket_brigade *bb = NULL;
> -    ap_bucket *b;
>
>      if (r->connection->aborted)
>          return EOF;
>      if (nbyte == 0)
>          return 0;
>
> -    bb = ap_brigade_create(r->pool);
> -    b = ap_bucket_create_transient(buf, nbyte);
> -    AP_BRIGADE_INSERT_TAIL(bb, b);
> +    coalesce_buf_insertb(r, bb, buf, nbyte);
> +    if (bb)
>      ap_pass_brigade(r->output_filters, bb);
> +
>      return nbyte;
>  }
>
> @@ -2956,13 +3001,18 @@
>  {
>      ap_bucket_brigade *bb = NULL;
>      apr_size_t written;
> +    int send_it = 0;
>
>      if (r->connection->aborted)
>          return EOF;
>
>      bb = ap_brigade_create(r->pool);
> +    if (r->coalesce_cnt > 0) {
> +        coalesce_buf_create_bucket(r, bb);
> +        send_it = 1;
> +    }
>      written = ap_brigade_vprintf(bb, fmt, va);
> -    if (written != 0)
> +    if (written != 0 || send_it != 0)
>          ap_pass_brigade(r->output_filters, bb);
>      return written;
>  }
> @@ -2986,28 +3036,43 @@
>  }
>
>  AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r, ...)
> -{
> + {
>      ap_bucket_brigade *bb = NULL;
>      apr_size_t written;
> +    const char *str;
> +    int len;
>      va_list va;
>
>      if (r->connection->aborted)
>          return EOF;
> -    bb = ap_brigade_create(r->pool);
> +
>      va_start(va, r);
> -    written = ap_brigade_vputstrs(bb, va);
> +    for (written = 0;;) {
> +        str = va_arg(va, const char *);
> +        if (str == NULL)
> +            break;
> +        len = strlen(str);
> +        coalesce_buf_insertb(r, bb, str, len);
> +        written += len;
> +    }
>      va_end(va);
> -    if (written != 0)
> +    if (written != 0 && bb)
>          ap_pass_brigade(r->output_filters, bb);
>      return written;
>  }
>
>  AP_DECLARE(int) ap_rflush(request_rec *r)
>  {
> -    /* we should be using a flush bucket to flush the stack, not buff code.
*/
>      ap_bucket_brigade *bb;
>      ap_bucket *b;
>
> +    if (r->coalesce_cnt > 0) {
> +        bb = ap_brigade_create(r->pool);
> +        coalesce_buf_create_bucket(r, bb);
> +        ap_pass_brigade(r->output_filters, bb);
> +    }
> +
> +    /* we should be using a flush bucket to flush the stack, not buff code.
*/
>      bb = ap_brigade_create(r->pool);
>      b = ap_bucket_create_flush();
>      AP_BRIGADE_INSERT_TAIL(bb, b);
>
> Victor
> --
> Victor J. Orlikowski
> ======================
> v.j.orlikowski@gte.net
> vjo@raleigh.ibm.com
> vjo@us.ibm.com
>


Mime
View raw message