[nginx] svn commit: r4389 - in trunk: auto auto/lib/pcre src/core

vbart at nginx.com vbart at nginx.com
Mon Dec 26 13:10:36 UTC 2011


Author: vbart
Date: 2011-12-26 13:10:36 +0000 (Mon, 26 Dec 2011)
New Revision: 4389

Log:
Added support for regex study and PCRE JIT (ticket #41) optimizations on
configuration phase.


Modified:
   trunk/auto/lib/pcre/conf
   trunk/auto/lib/pcre/make
   trunk/auto/modules
   trunk/auto/options
   trunk/auto/sources
   trunk/src/core/ngx_regex.c
   trunk/src/core/ngx_regex.h

Modified: trunk/auto/lib/pcre/conf
===================================================================
--- trunk/auto/lib/pcre/conf	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/auto/lib/pcre/conf	2011-12-26 13:10:36 UTC (rev 4389)
@@ -4,8 +4,6 @@
 
 if [ $PCRE != NONE ]; then
     CORE_INCS="$CORE_INCS $PCRE"
-    CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
-    CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
 
     case "$NGX_CC_NAME" in
 
@@ -81,6 +79,12 @@
 
     esac
 
+
+    if [ $PCRE_JIT = YES ]; then
+        have=NGX_HAVE_PCRE_JIT . auto/have
+        PCRE_CONF_OPT="$PCRE_CONF_OPT --enable-jit"
+    fi
+
 else
 
     if [ "$NGX_PLATFORM" != win32 ]; then
@@ -156,12 +160,23 @@
         fi
 
         if [ $ngx_found = yes ]; then
-            CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
-            CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
             CORE_INCS="$CORE_INCS $ngx_feature_path"
             CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
             PCRE=YES
         fi
+
+        if [ $PCRE == YES ]; then
+            ngx_feature="PCRE JIT support"
+            ngx_feature_name="NGX_HAVE_PCRE_JIT"
+            ngx_feature_test="int jit = 0;
+                              pcre_config(PCRE_CONFIG_JIT, &jit);
+                              if (jit != 1) return 1;"
+            . auto/feature
+
+            if [ $ngx_found = yes ]; then
+                PCRE_JIT=YES
+            fi
+        fi
     fi
 
     if [ $PCRE != YES ]; then

Modified: trunk/auto/lib/pcre/make
===================================================================
--- trunk/auto/lib/pcre/make	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/auto/lib/pcre/make	2011-12-26 13:10:36 UTC (rev 4389)
@@ -50,7 +50,7 @@
 	cd $PCRE \\
 	&& if [ -f Makefile ]; then \$(MAKE) distclean; fi \\
 	&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
-	./configure --disable-shared
+	./configure --disable-shared $PCRE_CONF_OPT
 
 $PCRE/.libs/libpcre.a:	$PCRE/Makefile
 	cd $PCRE \\

Modified: trunk/auto/modules
===================================================================
--- trunk/auto/modules	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/auto/modules	2011-12-26 13:10:36 UTC (rev 4389)
@@ -396,6 +396,12 @@
     CORE_SRCS="$CORE_SRCS $OPENSSL_SRCS"
 fi
 
+if [ $USE_PCRE = YES ]; then
+    modules="$modules $REGEX_MODULE"
+    CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
+    CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
+fi
+
 if [ $HTTP = YES ]; then
     modules="$modules $HTTP_MODULES $HTTP_FILTER_MODULES \
              $HTTP_HEADERS_FILTER_MODULE \

Modified: trunk/auto/options
===================================================================
--- trunk/auto/options	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/auto/options	2011-12-26 13:10:36 UTC (rev 4389)
@@ -111,6 +111,8 @@
 USE_PCRE=NO
 PCRE=NONE
 PCRE_OPT=
+PCRE_CONF_OPT=
+PCRE_JIT=NO
 
 USE_OPENSSL=NO
 OPENSSL=NONE
@@ -274,6 +276,7 @@
         --with-pcre)                     USE_PCRE=YES               ;;
         --with-pcre=*)                   PCRE="$value"              ;;
         --with-pcre-opt=*)               PCRE_OPT="$value"          ;;
+        --with-pcre-jit)                 PCRE_JIT=YES               ;;
 
         --with-openssl=*)                OPENSSL="$value"           ;;
         --with-openssl-opt=*)            OPENSSL_OPT="$value"       ;;
@@ -421,6 +424,7 @@
   --with-pcre                        force PCRE library usage
   --with-pcre=DIR                    set path to PCRE library sources
   --with-pcre-opt=OPTIONS            set additional build options for PCRE
+  --with-pcre-jit                    build PCRE with JIT compilation support
 
   --with-md5=DIR                     set path to md5 library sources
   --with-md5-opt=OPTIONS             set additional build options for md5

Modified: trunk/auto/sources
===================================================================
--- trunk/auto/sources	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/auto/sources	2011-12-26 13:10:36 UTC (rev 4389)
@@ -69,6 +69,7 @@
            src/core/ngx_crypt.c"
 
 
+REGEX_MODULE=ngx_regex_module
 REGEX_DEPS=src/core/ngx_regex.h
 REGEX_SRCS=src/core/ngx_regex.c
 

Modified: trunk/src/core/ngx_regex.c
===================================================================
--- trunk/src/core/ngx_regex.c	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/src/core/ngx_regex.c	2011-12-26 13:10:36 UTC (rev 4389)
@@ -8,11 +8,61 @@
 #include <ngx_core.h>
 
 
+typedef struct {
+    ngx_flag_t  pcre_jit;
+} ngx_regex_conf_t;
+
+
 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
 static void ngx_libc_cdecl ngx_regex_free(void *p);
 
+static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
 
+static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
+static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);
+
+static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
+static ngx_conf_post_t  ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
+
+
+static ngx_command_t  ngx_regex_commands[] = {
+
+    { ngx_string("pcre_jit"),
+      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_flag_slot,
+      0,
+      offsetof(ngx_regex_conf_t, pcre_jit),
+      &ngx_regex_pcre_jit_post },
+
+      ngx_null_command
+};
+
+
+static ngx_core_module_t  ngx_regex_module_ctx = {
+    ngx_string("regex"),
+    ngx_regex_create_conf,
+    ngx_regex_init_conf
+};
+
+
+ngx_module_t  ngx_regex_module = {
+    NGX_MODULE_V1,
+    &ngx_regex_module_ctx,                 /* module context */
+    ngx_regex_commands,                    /* module directives */
+    NGX_CORE_MODULE,                       /* module type */
+    NULL,                                  /* init master */
+    ngx_regex_module_init,                 /* init module */
+    NULL,                                  /* init process */
+    NULL,                                  /* init thread */
+    NULL,                                  /* exit thread */
+    NULL,                                  /* exit process */
+    NULL,                                  /* exit master */
+    NGX_MODULE_V1_PADDING
+};
+
+
 static ngx_pool_t  *ngx_pcre_pool;
+static ngx_list_t  *ngx_pcre_studies;
 
 
 void
@@ -62,10 +112,11 @@
 ngx_int_t
 ngx_regex_compile(ngx_regex_compile_t *rc)
 {
-    int           n, erroff;
-    char         *p;
-    const char   *errstr;
-    ngx_regex_t  *re;
+    int               n, erroff;
+    char             *p;
+    pcre             *re;
+    const char       *errstr;
+    ngx_regex_elt_t  *elt;
 
     ngx_regex_malloc_init(rc->pool);
 
@@ -92,8 +143,25 @@
         return NGX_ERROR;
     }
 
-    rc->regex = re;
+    rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
+    if (rc->regex == NULL) {
+        return NGX_ERROR;
+    }
 
+    rc->regex->pcre = re;
+
+    /* do not study at runtime */
+
+    if (ngx_pcre_studies != NULL) {
+        elt = ngx_list_push(ngx_pcre_studies);
+        if (elt == NULL) {
+            return NGX_ERROR;
+        }
+
+        elt->regex = rc->regex;
+        elt->name = rc->pattern.data;
+    }
+
     n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
     if (n < 0) {
         p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
@@ -203,3 +271,140 @@
 {
     return;
 }
+
+
+static ngx_int_t
+ngx_regex_module_init(ngx_cycle_t *cycle)
+{
+    int               opt;
+    const char       *errstr;
+    ngx_uint_t        i;
+    ngx_list_part_t  *part;
+    ngx_regex_elt_t  *elts;
+
+    opt = 0;
+
+#if (NGX_HAVE_PCRE_JIT)
+    {
+    ngx_regex_conf_t  *rcf;
+
+    rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
+
+    if (rcf->pcre_jit) {
+        opt = PCRE_STUDY_JIT_COMPILE;
+    }
+    }
+#endif
+
+    ngx_regex_malloc_init(cycle->pool);
+
+    part = &ngx_pcre_studies->part;
+    elts = part->elts;
+
+    for (i = 0 ; /* void */ ; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            elts = part->elts;
+            i = 0;
+        }
+
+        elts[i].regex->extra = pcre_study(elts[i].regex->pcre, opt, &errstr);
+
+        if (errstr != NULL) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                          "pcre_study() failed: %s in \"%s\"",
+                          errstr, elts[i].name);
+        }
+
+#if (NGX_HAVE_PCRE_JIT)
+        if (opt & PCRE_STUDY_JIT_COMPILE) {
+            int jit, n;
+
+            jit = 0;
+            n = pcre_fullinfo(elts[i].regex->pcre, elts[i].regex->extra,
+                              PCRE_INFO_JIT, &jit);
+
+            if (n != 0 || jit != 1) {
+                ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
+                              "JIT compiler does not support pattern: \"%s\"",
+                              elts[i].name);
+            }
+        }
+#endif
+    }
+
+    ngx_regex_malloc_done();
+
+    ngx_pcre_studies = NULL;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_regex_create_conf(ngx_cycle_t *cycle)
+{
+    ngx_regex_conf_t  *rcf;
+
+    rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
+    if (rcf == NULL) {
+        return NULL;
+    }
+
+    rcf->pcre_jit = NGX_CONF_UNSET;
+
+    ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
+    if (ngx_pcre_studies == NULL) {
+        return NULL;
+    }
+
+    return rcf;
+}
+
+
+static char *
+ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
+{
+    ngx_regex_conf_t *rcf = conf;
+
+    ngx_conf_init_value(rcf->pcre_jit, 0);
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
+{
+    ngx_flag_t  *fp = data;
+
+    if (*fp == 0) {
+        return NGX_CONF_OK;
+    }
+
+#if (NGX_HAVE_PCRE_JIT)
+    {
+    int  jit, r;
+
+    jit = 0;
+    r = pcre_config(PCRE_CONFIG_JIT, &jit);
+
+    if (r != 0 || jit != 1) {
+        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                           "PCRE library does not support JIT");
+        *fp = 0;
+    }
+    }
+#else
+    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                       "nginx was build without PCRE JIT support");
+    *fp = 0;
+#endif
+
+    return NGX_CONF_OK;
+}

Modified: trunk/src/core/ngx_regex.h
===================================================================
--- trunk/src/core/ngx_regex.h	2011-12-26 11:33:11 UTC (rev 4388)
+++ trunk/src/core/ngx_regex.h	2011-12-26 13:10:36 UTC (rev 4389)
@@ -18,9 +18,13 @@
 
 #define NGX_REGEX_CASELESS    PCRE_CASELESS
 
-typedef pcre  ngx_regex_t;
 
+typedef struct {
+    pcre        *pcre;
+    pcre_extra  *extra;
+} ngx_regex_t;
 
+
 typedef struct {
     ngx_str_t     pattern;
     ngx_pool_t   *pool;
@@ -45,7 +49,7 @@
 ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
 
 #define ngx_regex_exec(re, s, captures, size)                                \
-    pcre_exec(re, NULL, (const char *) (s)->data, (s)->len, 0, 0,            \
+    pcre_exec(re->pcre, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
               captures, size)
 #define ngx_regex_exec_n      "pcre_exec()"
 



More information about the nginx-devel mailing list