Added support for regex study and PCRE JIT (ticket #41) optimizations on
configuration phase.
This commit is contained in:
parent
2e6a0bc9a3
commit
498cc8846a
7 changed files with 247 additions and 12 deletions
|
@ -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 @@ 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
|
||||
|
@ -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
|
||||
|
|
|
@ -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 \\
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -111,6 +111,8 @@ NGX_ADDONS=
|
|||
USE_PCRE=NO
|
||||
PCRE=NONE
|
||||
PCRE_OPT=
|
||||
PCRE_CONF_OPT=
|
||||
PCRE_JIT=NO
|
||||
|
||||
USE_OPENSSL=NO
|
||||
OPENSSL=NONE
|
||||
|
@ -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" ;;
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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_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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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()"
|
||||
|
||||
|
|
Loading…
Reference in a new issue