]> granicus.if.org Git - apache/commitdiff
Performance optimization: use a temp buffer on the stack instead
authorBrian Pane <brianp@apache.org>
Thu, 21 Mar 2002 04:17:11 +0000 (04:17 +0000)
committerBrian Pane <brianp@apache.org>
Thu, 21 Mar 2002 04:17:11 +0000 (04:17 +0000)
of a malloc'ed buffer in regexec() in cases where the required
buffer size is small.

This will help us avoid a malloc/free pair when executing mod_rewrite
rules that use $1/$2/etc to reference sequences in the matched pattern.

Note: I've also submitted this change as a patch for PCRE, but because
the next PCRE release isn't planned until later this year I'm
committing it to the httpd-2.0 copy of PCRE in the meantime.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@94069 13f79535-47bb-0310-9956-ffa450edef68

srclib/pcre/pcreposix.c

index 9b2efe209877d8f953dfe14c5fa6295c20384e94..29f2e01740555e034df33705894aa6aa47059c93 100644 (file)
@@ -224,13 +224,23 @@ substring, so we have to get and release working store instead of just using
 the POSIX structures as was done in earlier releases when PCRE needed only 2
 ints. */
 
+#define SMALL_NMATCH 5
 int
 regexec(regex_t *preg, const char *string, size_t nmatch,
   regmatch_t pmatch[], int eflags)
 {
 int rc;
 int options = 0;
+/* NOTE: The code related to the "SMALL_NMATCH" optimization
+ * currently is unique to the httpd-2.0 copy of PCRE 3.9.  I've
+ * submitted the patch to the PCRE maintainer for inclusion in
+ * the next PCRE release, slated for late 2002.  At that time,
+ * we can merge the new PCRE version into the httpd-2.0/srclib
+ * tree.  --brianp 3/20/2002
+ */
+int small_ovector[SMALL_NMATCH * 3];
 int *ovector = NULL;
+int allocated_ovector = 0;
 
 if ((eflags & REG_NOTBOL) != 0) options |= PCRE_NOTBOL;
 if ((eflags & REG_NOTEOL) != 0) options |= PCRE_NOTEOL;
@@ -244,8 +254,16 @@ preg->re_erroffset = (size_t)(-1);   /* Only has meaning after compile */
 
 if (nmatch > 0)
   {
-  ovector = (int *)malloc(sizeof(int) * nmatch * 3);
-  if (ovector == NULL) return REG_ESPACE;
+    if (nmatch <= SMALL_NMATCH)
+      {
+      ovector = &(small_ovector[0]);
+      }
+    else
+      {
+      ovector = (int *)malloc(sizeof(int) * nmatch * 3);
+      if (ovector == NULL) return REG_ESPACE;
+      allocated_ovector = 1;
+      }
   }
 
 rc = pcre_exec(preg->re_pcre, NULL, string, (int)strlen(string), 0, options,
@@ -261,14 +279,14 @@ if (rc >= 0)
     pmatch[i].rm_so = ovector[i*2];
     pmatch[i].rm_eo = ovector[i*2+1];
     }
-  if (ovector != NULL) free(ovector);
+  if (allocated_ovector) free(ovector);
   for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
   return 0;
   }
 
 else
   {
-  if (ovector != NULL) free(ovector);
+  if (allocated_ovector) free(ovector);
   switch(rc)
     {
     case PCRE_ERROR_NOMATCH: return REG_NOMATCH;