Compare commits

...

14 commits
2.0 ... mempool

Author SHA1 Message Date
c9s
7251740668 Add mempool to Makefile.am 2015-11-12 22:15:40 +08:00
c9s
e09667818e Add mempool 2015-11-12 22:15:35 +08:00
c9s
576d568c16 use __attribute aligned to align struct 2015-11-12 22:01:55 +08:00
c9s
2dc8cc1533 Adjust window size 2015-11-11 11:17:43 +08:00
c9s
ae191a1d75 Add padding to node struct 2015-11-11 11:16:19 +08:00
c9s
60376804b0 Add 2.0 to changelog 2015-11-11 11:08:35 +08:00
c9s
257ced4717 Add padding to edge structure 2015-11-11 11:08:09 +08:00
c9s
985c8593dd Remove unneccessary comments from struct 2015-11-10 21:02:47 +08:00
c9s
7e08440d0c Merge branch 'gnu-likely' into 2.0 2015-11-10 20:43:16 +08:00
c9s
3041469007 Move variable positions 2015-11-10 20:42:41 +08:00
c9s
7e545159a0 Add GNU likely/unlikely support 2015-11-10 20:41:52 +08:00
c9s
e401364869 Cache pointer of edge 2015-11-10 20:31:36 +08:00
c9s
03448d72cf Merge branch 'edge-array' into 2.0 2015-11-10 20:30:07 +08:00
c9s
fd9388437e Make edges as an array
Fixes: #89
2015-11-10 20:29:07 +08:00
11 changed files with 175 additions and 74 deletions

View file

@ -3,6 +3,11 @@
by Yo-An Lin <yoanlin93@gmail.com> by Yo-An Lin <yoanlin93@gmail.com>
### 2.0 - Wed Nov 11 11:08:22 2015
### 1.3.3 - Sat Jun 28 00:53:48 2014 ### 1.3.3 - Sat Jun 28 00:53:48 2014
- Fix graphviz generator. - Fix graphviz generator.

View file

@ -150,12 +150,17 @@
var lines = data.split(/\n/); var lines = data.split(/\n/);
// keep window size to 30 records // keep window size to 60 records
lines.splice(-30); lines = lines.splice(-60);
lines = lines.splice(lines.length - 30);
$(lines).each(function(i,line) { $(lines).each(function(i,line) {
if (line == "") {
return;
}
var columns = line.split(/,/); var columns = line.split(/,/);
if (columns.length == 0) {
return;
}
var a; var a;
a = parseInt(columns[1]); a = parseInt(columns[1]);
options.series[0].data.push(a || 0); options.series[0].data.push(a || 0);

View file

@ -626,3 +626,19 @@
1447156411,13229275.90,5858750.37,66576.25,2523350.73 1447156411,13229275.90,5858750.37,66576.25,2523350.73
1447156432,13556025.90,5873947.56,62601.55,2487130.01 1447156432,13556025.90,5873947.56,62601.55,2487130.01
1447156745,13744909.39,5913103.69,66576.25,2551782.92 1447156745,13744909.39,5913103.69,66576.25,2551782.92
1447158285,11638128.71,5241775.30,71089.90,2321077.83
1447158396,13539837.29,5874704.47,47662.55,2533571.93
1447158415,14054879.53,5952300.47,41527.76,2571669.83
1447210457,13616841.50,5604087.24,83886.08,2458628.97
1447210807,14529897.99,5833087.33,77672.30,1845729.06
1447210834,14016924.69,5806227.80,66576.25,1715107.19
1447211104,14738120.40,5873312.56,58254.22,2092537.05
1447211128,14875503.82,5649431.95,27776.85,2033045.40
1447211244,15335902.86,6019829.26,77672.30,1842297.15
1447211259,14365504.46,5812325.12,91180.52,1965977.09
1447211278,15175749.51,5931324.37,99864.38,1905029.23
1447211529,15442994.79,5909448.56,91180.52,1953744.42
1447211564,15175229.72,6100062.87,58254.22,1918667.68
1447211712,15957717.02,6145969.23,77672.30,1960098.15
1447211732,15692151.82,5725138.47,62601.55,1711560.29
1447211755,15758474.73,6033801.22,82241.25,1995758.04

Can't render this file because it has a wrong number of fields in line 447.

View file

@ -28,39 +28,27 @@ typedef struct _node node;
typedef struct _route route; typedef struct _route route;
struct _node { struct _node {
edge ** edges; edge * edges;
// edge ** edge_table;
char * combined_pattern; char * combined_pattern;
pcre * pcre_pattern; pcre * pcre_pattern;
// #ifdef PCRE_STUDY_JIT_COMPILE
pcre_extra * pcre_extra; pcre_extra * pcre_extra;
// #endif
// edges are mostly less than 255 // edges are mostly less than 255
unsigned int edge_len;
unsigned int compare_type; // compare_type: pcre, opcode, string unsigned int compare_type; // compare_type: pcre, opcode, string
unsigned char endpoint; // endpoint, should be zero for non-endpoint nodes unsigned int edge_len;
unsigned char ov_cnt; // capture vector array size for pcre unsigned int endpoint; // endpoint, should be zero for non-endpoint nodes
unsigned int ov_cnt; // capture vector array size for pcre
route ** routes;
// the pointer of route data
void * data;
// almost less than 255 // almost less than 255
unsigned char edge_cap; unsigned char edge_cap;
unsigned char route_len; unsigned char route_len;
unsigned char route_cap; unsigned char route_cap;
// <-- here comes a char[1] struct padding for alignment since we have 4 char above. } __attribute((aligned(64)));
/** compile-time variables here.... **/
/* the combined regexp pattern string from pattern_tokens */
route ** routes;
/**
* the pointer of route data
*/
void * data;
};
#define r3_node_edge_pattern(node,i) node->edges[i]->pattern #define r3_node_edge_pattern(node,i) node->edges[i]->pattern
#define r3_node_edge_pattern_len(node,i) node->edges[i]->pattern_len #define r3_node_edge_pattern_len(node,i) node->edges[i]->pattern_len
@ -68,11 +56,10 @@ struct _node {
struct _edge { struct _edge {
char * pattern; // 8 bytes char * pattern; // 8 bytes
node * child; // 8 bytes node * child; // 8 bytes
unsigned int pattern_len; // 1 byte unsigned int pattern_len; // 4byte
unsigned int opcode; unsigned int opcode; // 4byte
// unsigned char opcode:4; // 4 bit unsigned int has_slug; // 4byte
unsigned char has_slug:1; // 1 bit } __attribute((aligned(64)));
};
struct _route { struct _route {
char * path; char * path;
@ -87,7 +74,7 @@ struct _route {
char * remote_addr_pattern; char * remote_addr_pattern;
int remote_addr_pattern_len; int remote_addr_pattern_len;
}; } __attribute((aligned(64)));
typedef struct { typedef struct {
str_array * vars; str_array * vars;
@ -123,7 +110,7 @@ edge * r3_node_connectl(node * n, const char * pat, int len, int strdup, node *c
edge * r3_node_find_edge(const node * n, const char * pat, int pat_len); edge * r3_node_find_edge(const node * n, const char * pat, int pat_len);
void r3_node_append_edge(node *n, edge *child); edge * r3_node_append_edge(node *n, edge *child);
edge * r3_node_find_common_prefix(node *n, const char *path, int path_len, int *prefix_len, char **errstr); edge * r3_node_find_common_prefix(node *n, const char *path, int path_len, int *prefix_len, char **errstr);
@ -171,6 +158,8 @@ bool r3_node_has_slug_edges(const node *n);
edge * r3_edge_createl(const char * pattern, int pattern_len, node * child); edge * r3_edge_createl(const char * pattern, int pattern_len, node * child);
void r3_edge_initl(edge *e, const char * pattern, int pattern_len, node * child);
node * r3_edge_branch(edge *e, int dl); node * r3_edge_branch(edge *e, int dl);
void r3_edge_free(edge * edge); void r3_edge_free(edge * edge);

View file

@ -4,7 +4,7 @@ MAYBE_COVERAGE=--coverage
noinst_LTLIBRARIES = libr3core.la noinst_LTLIBRARIES = libr3core.la
# lib_LIBRARIES = libr3.a # lib_LIBRARIES = libr3.a
libr3core_la_SOURCES = node.c edge.c str.c token.c match_entry.c slug.c libr3core_la_SOURCES = node.c edge.c str.c token.c match_entry.c slug.c mempool.c
if ENABLE_JSON if ENABLE_JSON
libr3core_la_SOURCES += json.c libr3core_la_SOURCES += json.c

View file

@ -24,11 +24,20 @@
#define CHECK_PTR(ptr) if (ptr == NULL) return NULL; #define CHECK_PTR(ptr) if (ptr == NULL) return NULL;
edge * r3_edge_createl(const char * pattern, int pattern_len, node * child) {
void r3_edge_initl(edge *e, const char * pattern, int pattern_len, node * child)
{
e->pattern = (char*) pattern;
e->pattern_len = pattern_len;
e->opcode = 0;
e->child = child;
e->has_slug = r3_path_contains_slug_char(e->pattern);
}
edge * r3_edge_createl(const char * pattern, int pattern_len, node * child)
{
edge * e = (edge*) zmalloc( sizeof(edge) ); edge * e = (edge*) zmalloc( sizeof(edge) );
CHECK_PTR(e); CHECK_PTR(e);
e->pattern = (char*) pattern; e->pattern = (char*) pattern;
e->pattern_len = pattern_len; e->pattern_len = pattern_len;
e->opcode = 0; e->opcode = 0;
@ -60,9 +69,9 @@ node * r3_edge_branch(edge *e, int dl) {
e1 = r3_edge_createl(zstrndup(s1, s1_len), s1_len, new_child); e1 = r3_edge_createl(zstrndup(s1, s1_len), s1_len, new_child);
// Migrate the child edges to the new edge we just created. // Migrate the child edges to the new edge we just created.
for ( int i = 0 ; i < e->child->edge_len ; i++ ) { for (int i = 0 ; i < e->child->edge_len ; i++) {
r3_node_append_edge(new_child, e->child->edges[i]); r3_node_append_edge(new_child, &e->child->edges[i]);
e->child->edges[i] = NULL; // e->child->edges[i] = NULL;
} }
e->child->edge_len = 0; e->child->edge_len = 0;

43
src/mempool.c Normal file
View file

@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include "mempool.h"
void ex_mpool_init(ex_mpool *pmp, char *begin, size_t len)
{
pmp->begin = begin;
pmp->len = len;
pmp->index = 0;
pmp->cflag = 0;
}
void *ex_mpool_malloc(ex_mpool *pmp, size_t mlen)
{
void *ret = NULL;
size_t rIndex = pmp->index + mlen;
if (rIndex > pmp->len) {
ret = malloc(mlen);
pmp->cflag = 1;
}
else {
ret = pmp->begin + pmp->index;
pmp->index = rIndex;
}
return ret;
}
void ex_mpool_free(ex_mpool *pmp, void *p)
{
/* only perform free when allocated in heap */
if (p < (void *) pmp->begin ||
p >= (void *) (pmp->begin + pmp->len)) {
free(p);
}
}
void ex_mpool_clear(ex_mpool *pmp)
{
pmp->index = 0;
pmp->cflag = 0;
}

24
src/mempool.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef __ESERV_MPOOL_H__
#define __ESERV_MPOOL_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
char *begin; /* start pos */
size_t len; /* capacity */
int index; /* curIndex */
int cflag; /* clear flag */
} ex_mpool;
void ex_mpool_init(ex_mpool *pmp, char *begin, size_t len);
void *ex_mpool_malloc(ex_mpool *pmp, size_t mlen);
void ex_mpool_free(ex_mpool *pmp, void *p);
void ex_mpool_clear(ex_mpool *pmp);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -13,6 +13,13 @@
#include "slug.h" #include "slug.h"
#include "zmalloc.h" #include "zmalloc.h"
#ifdef __GNUC__
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#else
# define likely(x) !!(x)
# define unlikely(x) !!(x)
#endif
#define CHECK_PTR(ptr) if (ptr == NULL) return NULL; #define CHECK_PTR(ptr) if (ptr == NULL) return NULL;
@ -47,7 +54,7 @@ node * r3_tree_create(int cap) {
node * n = (node*) zmalloc( sizeof(node) ); node * n = (node*) zmalloc( sizeof(node) );
CHECK_PTR(n); CHECK_PTR(n);
n->edges = (edge**) zmalloc( sizeof(edge*) * cap ); n->edges = (edge*) zmalloc(sizeof(edge) * cap);
CHECK_PTR(n->edges); CHECK_PTR(n->edges);
n->edge_len = 0; n->edge_len = 0;
n->edge_cap = cap; n->edge_cap = cap;
@ -65,12 +72,9 @@ node * r3_tree_create(int cap) {
} }
void r3_tree_free(node * tree) { void r3_tree_free(node * tree) {
for (int i = 0 ; i < tree->edge_len ; i++ ) { if (tree->edges) {
if (tree->edges[i]) {
r3_edge_free(tree->edges[ i ]);
}
}
zfree(tree->edges); zfree(tree->edges);
}
zfree(tree->routes); zfree(tree->routes);
if (tree->pcre_pattern) { if (tree->pcre_pattern) {
pcre_free(tree->pcre_pattern); pcre_free(tree->pcre_pattern);
@ -104,23 +108,29 @@ edge * r3_node_connectl(node * n, const char * pat, int len, int dupl, node *chi
} }
e = r3_edge_createl(pat, len, child); e = r3_edge_createl(pat, len, child);
CHECK_PTR(e); CHECK_PTR(e);
r3_node_append_edge(n, e); edge *e2 = r3_node_append_edge(n, e);
return e; zfree(e);
return e2;
} }
void r3_node_append_edge(node *n, edge *e) { edge * r3_node_append_edge(node *n, edge *e)
{
if (n->edges == NULL) { if (n->edges == NULL) {
n->edge_cap = 3; n->edge_cap = 3;
n->edges = zmalloc(sizeof(edge) * n->edge_cap); n->edges = zmalloc(sizeof(edge) * n->edge_cap);
} }
if (n->edge_len >= n->edge_cap) { if (n->edge_len >= n->edge_cap) {
n->edge_cap *= 2; n->edge_cap *= 2;
edge ** p = zrealloc(n->edges, sizeof(edge) * n->edge_cap); edge * p = zrealloc(n->edges, sizeof(edge) * n->edge_cap);
if(p) { if(p) {
n->edges = p; n->edges = p;
} }
} }
n->edges[ n->edge_len++ ] = e;
// r3_edge_initl(
// copy 'edge' into the edge array
n->edges[n->edge_len] = *e;
return &n->edges[n->edge_len++];
} }
@ -133,11 +143,10 @@ edge * r3_node_find_edge(const node * n, const char * pat, int pat_len) {
edge * e; edge * e;
int i; int i;
for (i = 0 ; i < n->edge_len ; i++ ) { for (i = 0 ; i < n->edge_len ; i++ ) {
e = n->edges[i]; e = &n->edges[i];
// there is a case: "{foo}" vs "{foo:xxx}", // there is a case: "{foo}" vs "{foo:xxx}",
// we should return the match result: full-match or partial-match // we should return the match result: full-match or partial-match
if ( strcmp(e->pattern, pat) == 0 ) { if (strcmp(e->pattern, pat) == 0) {
return e; return e;
} }
} }
@ -146,6 +155,7 @@ edge * r3_node_find_edge(const node * n, const char * pat, int pat_len) {
int r3_tree_compile(node *n, char **errstr) int r3_tree_compile(node *n, char **errstr)
{ {
int i;
int ret = 0; int ret = 0;
bool use_slug = r3_node_has_slug_edges(n); bool use_slug = r3_node_has_slug_edges(n);
if ( use_slug ) { if ( use_slug ) {
@ -157,8 +167,8 @@ int r3_tree_compile(node *n, char **errstr)
n->combined_pattern = NULL; n->combined_pattern = NULL;
} }
for (int i = 0 ; i < n->edge_len ; i++ ) { for (i = 0 ; i < n->edge_len ; i++ ) {
if ( (ret = r3_tree_compile(n->edges[i]->child, errstr)) ) { if ((ret = r3_tree_compile(n->edges[i].child, errstr))) {
return ret; // stop here if error occurs return ret; // stop here if error occurs
} }
} }
@ -173,7 +183,7 @@ int r3_tree_compile(node *n, char **errstr)
* Return 0 if success * Return 0 if success
*/ */
int r3_tree_compile_patterns(node * n, char **errstr) { int r3_tree_compile_patterns(node * n, char **errstr) {
edge * e = NULL; edge *e = NULL;
char * p; char * p;
char * cpat = zcalloc(sizeof(char) * 64 * 3); // XXX char * cpat = zcalloc(sizeof(char) * 64 * 3); // XXX
if (!cpat) { if (!cpat) {
@ -185,7 +195,7 @@ int r3_tree_compile_patterns(node * n, char **errstr) {
int opcode_cnt = 0; int opcode_cnt = 0;
int i = 0; int i = 0;
for (; i < n->edge_len ; i++) { for (; i < n->edge_len ; i++) {
e = n->edges[i]; e = &n->edges[i];
if (e->opcode) { if (e->opcode) {
opcode_cnt++; opcode_cnt++;
} }
@ -286,7 +296,7 @@ node * r3_tree_matchl(const node * n, const char * path, int path_len, match_ent
for (i = n->edge_len; i--; ) { for (i = n->edge_len; i--; ) {
pp = path; pp = path;
e = n->edges[i]; e = &n->edges[i];
switch(e->opcode) { switch(e->opcode) {
case OP_EXPECT_NOSLASH: case OP_EXPECT_NOSLASH:
while (*pp != '/' && pp < pp_end) pp++; while (*pp != '/' && pp < pp_end) pp++;
@ -305,7 +315,7 @@ node * r3_tree_matchl(const node * n, const char * path, int path_len, match_ent
break; break;
} }
// check match // check match
if ( (pp - path) > 0) { if ((pp - path) > 0) {
if (entry) { if (entry) {
str_array_append(entry->vars , zstrndup(path, pp - path)); str_array_append(entry->vars , zstrndup(path, pp - path));
} }
@ -372,7 +382,7 @@ node * r3_tree_matchl(const node * n, const char * path, int path_len, match_ent
continue; continue;
substring_start = path + ov[2*i]; substring_start = path + ov[2*i];
e = n->edges[i - 1]; e = &n->edges[i - 1];
if (entry && e->has_slug) { if (entry && e->has_slug) {
// append captured token to entry // append captured token to entry
@ -396,7 +406,7 @@ node * r3_tree_matchl(const node * n, const char * path, int path_len, match_ent
} }
substring_start = path + ov[2*i]; substring_start = path + ov[2*i];
e = n->edges[i - 1]; e = &n->edges[i - 1];
if (entry && e->has_slug) { if (entry && e->has_slug) {
// append captured token to entry // append captured token to entry
@ -410,7 +420,7 @@ node * r3_tree_matchl(const node * n, const char * path, int path_len, match_ent
return NULL; return NULL;
} }
if ( (e = r3_node_find_edge_str(n, path, path_len)) != NULL ) { if ((e = r3_node_find_edge_str(n, path, path_len)) != NULL) {
restlen = path_len - e->pattern_len; restlen = path_len - e->pattern_len;
if (restlen == 0) { if (restlen == 0) {
return e->child && e->child->endpoint > 0 ? e->child : NULL; return e->child && e->child->endpoint > 0 ? e->child : NULL;
@ -437,13 +447,14 @@ route * r3_tree_match_route(const node *tree, match_entry * entry) {
} }
inline edge * r3_node_find_edge_str(const node * n, const char * str, int str_len) { inline edge * r3_node_find_edge_str(const node * n, const char * str, int str_len) {
char firstbyte = *str; edge * e;
unsigned int i; unsigned int i;
char firstbyte = *str;
for (i = n->edge_len; i--; ) { for (i = n->edge_len; i--; ) {
edge *e = n->edges[i]; e = &n->edges[i];
if (firstbyte == e->pattern[0]) { if (firstbyte == e->pattern[0]) {
if (strncmp(e->pattern, str, e->pattern_len) == 0 ) { if (strncmp(e->pattern, str, e->pattern_len) == 0) {
return n->edges[i]; return &n->edges[i];
} }
return NULL; return NULL;
} }
@ -531,11 +542,11 @@ edge * r3_node_find_common_prefix(node *n, const char *path, int path_len, int *
edge *e = NULL; edge *e = NULL;
for(i = 0 ; i < n->edge_len ; i++ ) { for(i = 0 ; i < n->edge_len ; i++ ) {
// ignore all edges with slug // ignore all edges with slug
prefix = strndiff( (char*) path, n->edges[i]->pattern, n->edges[i]->pattern_len); prefix = strndiff( (char*) path, n->edges[i].pattern, n->edges[i].pattern_len);
// no common, consider insert a new edge // no common, consider insert a new edge
if ( prefix > 0 ) { if ( prefix > 0 ) {
e = n->edges[i]; e = &n->edges[i];
break; break;
} }
} }
@ -753,7 +764,7 @@ bool r3_node_has_slug_edges(const node *n) {
bool found = FALSE; bool found = FALSE;
edge *e; edge *e;
for ( int i = 0 ; i < n->edge_len ; i++ ) { for ( int i = 0 ; i < n->edge_len ; i++ ) {
e = n->edges[i]; e = &n->edges[i];
e->has_slug = r3_path_contains_slug_char(e->pattern); e->has_slug = r3_path_contains_slug_char(e->pattern);
if (e->has_slug) if (e->has_slug)
found = TRUE; found = TRUE;
@ -780,7 +791,7 @@ void r3_tree_dump(const node * n, int level) {
printf("\n"); printf("\n");
for ( int i = 0 ; i < n->edge_len ; i++ ) { for ( int i = 0 ; i < n->edge_len ; i++ ) {
edge * e = n->edges[i]; edge * e = &n->edges[i];
print_indent(level + 1); print_indent(level + 1);
printf("|-\"%s\"", e->pattern); printf("|-\"%s\"", e->pattern);

View file

@ -1,5 +1,4 @@
# set(TEST_LIBS ${TEST_LIBS} ${CHECK_LIBRARIES} judy libr3) # set(TEST_LIBS ${TEST_LIBS} ${CHECK_LIBRARIES} judy libr3)
# set(TEST_LIBS ${TEST_LIBS} ${CHECK_LIBRARIES} judy libr3)
include_directories("${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}") include_directories("${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}")
find_package(Check REQUIRED) find_package(Check REQUIRED)
find_package(PCRE REQUIRED) find_package(PCRE REQUIRED)

View file

@ -20,7 +20,7 @@
unsigned long unixtime() { unsigned long unixtime() {
struct timeval tp; struct timeval tp;
if (gettimeofday((struct timeval *) &tp, (NUL)) == 0) { if (gettimeofday((struct timeval *) &tp, (NULL)) == 0) {
return tp.tv_sec; return tp.tv_sec;
} }
return 0; return 0;
@ -30,7 +30,7 @@ double microtime() {
struct timeval tp; struct timeval tp;
long sec = 0L; long sec = 0L;
double msec = 0.0; double msec = 0.0;
if (gettimeofday((struct timeval *) &tp, (NUL)) == 0) { if (gettimeofday((struct timeval *) &tp, (NULL)) == 0) {
msec = (double) (tp.tv_usec / MICRO_IN_SEC); msec = (double) (tp.tv_usec / MICRO_IN_SEC);
sec = tp.tv_sec; sec = tp.tv_sec;
if (msec >= 1.0) if (msec >= 1.0)