httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject [PATCH] invoke_handler speedup
Date Sat, 24 Jan 1998 22:35:01 GMT
Dmitry sent a patch for invoke_handler() a little while back, it's along
the same lines as my run_method() patch that went in right after 1.3 was
forked off of 1.2.  It "compiles" a much more compact representation of
the handlers and then uses that.

Ok so my simple test case is 5 simultaneous clients requesting a 6k
document, using keep-alive.  The box is a linux 2.0.30 dual pentium pro
166... I'm testing across loopback.  (I get similar ratios for a single
cpu box too.)

With current HEAD I get 662 req/s.
With Dmitry's patch I get 670 req/s.  (1.2% improvement)
With the patch below I get 686 req/s. (3.6% improvement)

The main difference in my patch below is that I precalculate the length of
each content type.  This gives some short-circuiting to the comparisons. 
Dmitry's patch uses pstrdup()/str_tolower() so that he can use the
comparatively less expensive strcmp()/strncmp() routines... but I found
that the pstrdup()/str_tolower() just costs too much.  So my patch doesn't
make any copy, but uses strncasecmp().

I'm concerned that other architectures' strncasecmp() may not be as
efficient as linux's...

Can some folks give this a try elsewhere? 

Dean

--- http_config.c.orig	Sat Jan 24 14:13:39 1998
+++ http_config.c	Sat Jan 24 14:16:53 1998
@@ -413,58 +413,112 @@
     return run_method(r, offsets_into_method_ptrs.auth_checker, 0);
 }
 
-int invoke_handler(request_rec *r)
+/*
+ * For speed/efficiency we generate a compact list of all the handlers
+ * and wildcard handlers.  This means we won't have to scan the entire
+ * module list looking for handlers... where we'll find a whole whack
+ * of NULLs.
+ */
+typedef struct {
+    handler_rec hr;
+    size_t len;
+} fast_handler_rec;
+
+static fast_handler_rec *handlers;
+static fast_handler_rec *wildhandlers;
+
+static void init_handlers(pool *p)
 {
     module *modp;
+    int nhandlers = 0;
+    int nwildhandlers = 0;
     handler_rec *handp;
-    char *content_type = r->content_type ? r->content_type : default_type(r);
-    char *handler, *p;
-
-    if ((p = strchr(content_type, ';')) != NULL) {	/* MIME type arguments */
-	while (p > content_type && p[-1] == ' ')
-	    --p;		/* strip trailing spaces */
-	content_type = pstrndup(r->pool, content_type, p - content_type);
-    }
-    handler = r->handler ? r->handler : content_type;
-
-    /* Pass one --- direct matches */
+    fast_handler_rec *ph, *pw;
+    char *ct;
+    char *starp;
 
     for (modp = top_module; modp; modp = modp->next) {
 	if (!modp->handlers)
 	    continue;
-
 	for (handp = modp->handlers; handp->content_type; ++handp) {
-	    if (!strcasecmp(handler, handp->content_type)) {
-		int result = (*handp->handler) (r);
-
-		if (result != DECLINED)
-		    return result;
-	    }
-	}
+	    if (strchr(handp->content_type, '*')) {
+                nwildhandlers ++;
+            } else {
+                nhandlers ++;
+            }
+        }
     }
-
-    /* Pass two --- wildcard matches */
-
+    ph = handlers = palloc(p, sizeof(*ph)*(nhandlers + 1));
+    pw = wildhandlers = palloc(p, sizeof(*pw)*(nwildhandlers + 1));
     for (modp = top_module; modp; modp = modp->next) {
 	if (!modp->handlers)
 	    continue;
-
 	for (handp = modp->handlers; handp->content_type; ++handp) {
-	    char *starp = strchr(handp->content_type, '*');
-	    int len;
+            ct = pstrdup(p, handp->content_type);
+            str_tolower(ct);
+	    if ((starp = strchr(handp->content_type, '*'))) {
+                pw->hr.content_type = ct;
+                pw->hr.handler = handp->handler;
+		pw->len = starp - handp->content_type;
+                pw ++;
+            } else {
+                ph->hr.content_type = ct;
+                ph->hr.handler = handp->handler;
+		ph->len = strlen(handp->content_type);
+                ph ++;
+            }
+        }
+    }
+    pw->hr.content_type = NULL;
+    pw->hr.handler = NULL;
+    ph->hr.content_type = NULL;
+    ph->hr.handler = NULL;
+}
+
+int invoke_handler(request_rec *r)
+{
+    fast_handler_rec *handp;
+    char *handler, *p;
+    size_t handler_len;
+
+    if (r->handler) {
+	handler = r->handler;
+	handler_len = strlen(handler);
+    }
+    else {
+	handler = r->content_type ? r->content_type : default_type(r);
+	if ((p = strchr(handler, ';')) != NULL) { /* MIME type arguments */
+	    while (p > handler && p[-1] == ' ')
+		--p;		/* strip trailing spaces */
+	    handler_len = p - handler;
+	}
+	else {
+	    handler_len = strlen(handler);
+	}
+    }
 
-	    if (!starp)
-		continue;
+    /* Pass one --- direct matches */
 
-	    len = starp - handp->content_type;
+    for (handp = handlers; handp->hr.content_type; ++handp) {
+	if (handler_len == handp->len
+	    && !strncasecmp(handler, handp->hr.content_type, handler_len)) {
+            int result = (*handp->hr.handler) (r);
+
+            if (result != DECLINED)
+                return result;
+        }
+    }
 
-	    if (!len || !strncasecmp(handler, handp->content_type, len)) {
-		int result = (*handp->handler) (r);
+    /* Pass two --- wildcard matches */
 
-		if (result != DECLINED)
-		    return result;
-	    }
-	}
+    for (handp = wildhandlers; handp->hr.content_type; ++handp) {
+	if (handler_len >= handp->len
+	    && !strncasecmp(handler, handp->hr.content_type, handp->len)) {
+             int result = (*handp->hr.handler) (r);
+
+             if (result != DECLINED)
+                 return result;
+         }
     }
 
     return NOT_IMPLEMENTED;
@@ -1300,6 +1354,7 @@
     for (m = top_module; m; m = m->next)
 	if (m->init)
 	    (*m->init) (s, p);
+    init_handlers(p);
 }
 
 void child_init_modules(pool *p, server_rec *s)




Mime
View raw message