Skip to content

Commit

Permalink
Added support for regex study and PCRE JIT (ticket #41) optimizations on
Browse files Browse the repository at this point in the history
configuration phase.
  • Loading branch information
vbart committed Dec 26, 2011
1 parent 8b0d476 commit 402fa8e
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 12 deletions.
23 changes: 19 additions & 4 deletions auto/lib/pcre/conf
Expand Up @@ -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

Expand Down Expand Up @@ -81,6 +79,12 @@ if [ $PCRE != NONE ]; then

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
Expand Down Expand Up @@ -156,12 +160,23 @@ else
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
Expand Down
2 changes: 1 addition & 1 deletion auto/lib/pcre/make
Expand Up @@ -50,7 +50,7 @@ $PCRE/Makefile: $NGX_MAKEFILE
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 \\
Expand Down
6 changes: 6 additions & 0 deletions auto/modules
Expand Up @@ -396,6 +396,12 @@ if [ $USE_OPENSSL = YES ]; then
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 \
Expand Down
4 changes: 4 additions & 0 deletions auto/options
Expand Up @@ -111,6 +111,8 @@ NGX_ADDONS=
USE_PCRE=NO
PCRE=NONE
PCRE_OPT=
PCRE_CONF_OPT=
PCRE_JIT=NO

USE_OPENSSL=NO
OPENSSL=NONE
Expand Down Expand Up @@ -274,6 +276,7 @@ use the \"--without-http_limit_conn_module\" option instead"
--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" ;;
Expand Down Expand Up @@ -421,6 +424,7 @@ cat << END
--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
Expand Down
1 change: 1 addition & 0 deletions auto/sources
Expand Up @@ -69,6 +69,7 @@ CORE_SRCS="src/core/nginx.c \
src/core/ngx_crypt.c"


REGEX_MODULE=ngx_regex_module
REGEX_DEPS=src/core/ngx_regex.h
REGEX_SRCS=src/core/ngx_regex.c

Expand Down
215 changes: 210 additions & 5 deletions src/core/ngx_regex.c
Expand Up @@ -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
Expand Down Expand Up @@ -62,10 +112,11 @@ ngx_regex_malloc_done(void)
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);

Expand All @@ -92,7 +143,24 @@ ngx_regex_compile(ngx_regex_compile_t *rc)
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) {
Expand Down Expand Up @@ -203,3 +271,140 @@ ngx_regex_free(void *p)
{
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;
}
8 changes: 6 additions & 2 deletions src/core/ngx_regex.h
Expand Up @@ -18,7 +18,11 @@

#define NGX_REGEX_CASELESS PCRE_CASELESS

typedef pcre ngx_regex_t;

typedef struct {
pcre *pcre;
pcre_extra *extra;
} ngx_regex_t;


typedef struct {
Expand All @@ -45,7 +49,7 @@ void ngx_regex_init(void);
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()"

Expand Down

0 comments on commit 402fa8e

Please sign in to comment.