httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Victor J. Orlikowski" <v.j.orlikow...@gte.net>
Subject [PATCH] ap_r* efficiency improvements
Date Tue, 14 Nov 2000 20:06:37 GMT
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