Add benchmark and bug fixes

This commit is contained in:
c9s 2014-05-16 18:03:52 +08:00
parent 6b39b72ebe
commit 046ec9e977
6 changed files with 550 additions and 131 deletions

View file

@ -12,8 +12,7 @@ typedef unsigned char bool;
#define FALSE 0
#define TRUE 1
#define DEBUG 1
// #define DEBUG 1
#ifdef DEBUG
#define info(fmt, ...) \

View file

@ -21,7 +21,6 @@ struct _node;
typedef struct _edge edge;
typedef struct _node node;
struct _node {
edge ** edges;
int edge_len;
@ -33,7 +32,6 @@ struct _node {
pcre * pcre_pattern;
pcre_extra * pcre_extra;
/**
* the pointer of route structure
*/
@ -49,6 +47,12 @@ struct _edge {
node * child;
};
typedef struct {
char ** vars;
int vars_len;
char * path; // dispatched path
void * route_ptr; // route ptr
} match_entry;
node * rtree_create(int cap);
@ -65,8 +69,6 @@ edge * node_find_edge(node * n, char * pat);
void rtree_append_edge(node *n, edge *child);
node * rtree_insert_tokens(node * tree, token_array * tokens);
node * rtree_insert_path(node *tree, char *route, void * route_ptr);
node * rtree_insert_pathn(node *tree, char *route, int route_len, void * route_ptr);
@ -80,7 +82,7 @@ void rtree_compile(node *n);
void rtree_compile_patterns(node * n);
node * rtree_match(node * n, char * path, int path_len);
node * rtree_match(node * n, char * path, int path_len, match_entry * entry);
bool node_has_slug_edges(node *n);
@ -92,4 +94,7 @@ void edge_branch(edge *e, int dl);
void edge_free(edge * edge);
#endif /* !NODE_H */

View file

@ -10,29 +10,29 @@
#include "define.h"
typedef struct _token_array {
typedef struct _str_array {
char **tokens;
int len;
int cap;
} token_array;
} str_array;
token_array * token_array_create(int cap);
str_array * str_array_create(int cap);
bool token_array_is_full(token_array * l);
bool str_array_is_full(str_array * l);
bool token_array_resize(token_array *l, int new_cap);
bool str_array_resize(str_array *l, int new_cap);
bool token_array_append(token_array * list, char * token);
bool str_array_append(str_array * list, char * token);
void token_array_free(token_array *l);
void str_array_free(str_array *l);
void token_array_dump(token_array *l);
void str_array_dump(str_array *l);
token_array * split_route_pattern(char *pattern, int pattern_len);
str_array * split_route_pattern(char *pattern, int pattern_len);
#define token_array_fetch(t,i) t->tokens[i]
#define token_array_len(t) t->len
#define token_array_cap(t) t->cap
#define str_array_fetch(t,i) t->tokens[i]
#define str_array_len(t) t->len
#define str_array_cap(t) t->cap
#endif /* !TOKEN_H */

View file

@ -45,7 +45,7 @@ void rtree_free(node * tree) {
free(tree->combined_pattern);
free(tree->edges);
// token_array_free(tree->edge_patterns);
// str_array_free(tree->edge_patterns);
free(tree);
tree = NULL;
}
@ -65,8 +65,8 @@ edge * rtree_add_child(node * n, char * pat , node *child) {
e = edge_create( pat, strlen(pat), child);
rtree_append_edge(n, e);
// token_array_append(n->edge_patterns, pat);
// assert( token_array_len(n->edge_patterns) == n->edge_len );
// str_array_append(n->edge_patterns, pat);
// assert( str_array_len(n->edge_patterns) == n->edge_len );
return e;
}
@ -127,6 +127,7 @@ void rtree_compile_patterns(node * n) {
p = cpat;
edge *e = NULL;
for ( int i = 0 ; i < n->edge_len ; i++ ) {
e = n->edges[i];
@ -152,6 +153,12 @@ void rtree_compile_patterns(node * n) {
const char *error;
int erroffset;
unsigned int option_bits;
if (n->pcre_pattern)
free(n->pcre_pattern);
if (n->pcre_extra)
free(n->pcre_extra);
// n->pcre_pattern;
n->pcre_pattern = pcre_compile(
@ -174,7 +181,9 @@ void rtree_compile_patterns(node * n) {
node * rtree_match(node * n, char * path, int path_len) {
node * rtree_match(node * n, char * path, int path_len, match_entry * entry) {
// info("try matching: %s\n", path);
if (n->combined_pattern && n->pcre_pattern) {
info("pcre matching %s on %s\n", n->combined_pattern, path);
// int ovector_count = (n->edge_len + 1) * 2;
@ -206,18 +215,27 @@ node * rtree_match(node * n, char * path, int path_len) {
}
int i;
edge *e;
for (i = 1; i < rc; i++)
{
char *substring_start = path + ovector[2*i];
int substring_length = ovector[2*i+1] - ovector[2*i];
info("%2d: %.*s\n", i, substring_length, substring_start);
if ( substring_length > 0) {
int restlen = path_len - ovector[2*i+1]; // fully match to the end
info("matched item => restlen:%d edges:%d i:%d\n", restlen, n->edge_len, i);
if (restlen) {
return rtree_match( n->edges[i - 1]->child, substring_start + substring_length, restlen);
e = n->edges[i - 1];
if (entry && e->has_slug) {
// entry->
}
return n->edges[i - 1]->child;
if (restlen == 0) {
return e->child;
}
return rtree_match( e->child, substring_start + substring_length, restlen, entry);
}
}
// does not match
@ -230,7 +248,7 @@ node * rtree_match(node * n, char * path, int path_len) {
if(len == 0) {
return e->child;
} else {
return rtree_match(e->child, path + e->pattern_len, len);
return rtree_match(e->child, path + e->pattern_len, len, entry);
}
}
return NULL;
@ -238,27 +256,43 @@ node * rtree_match(node * n, char * path, int path_len) {
edge * node_find_edge_str(node * n, char * str, int str_len) {
edge *e;
char *p;
char *s;
for ( int i = 0 ; i < n->edge_len ; i++ ) {
e = n->edges[i];
char *p = e->pattern;
while ( *p == *str ) {
p++;
p = e->pattern;
s = str;
info("matching '%s' with '%s'\n", str, e->pattern);
if ( str_len < e->pattern_len ) {
continue;
}
if ( strncmp(e->pattern, str, e->pattern_len) == 0 ) {
return e;
}
/*
while ( *p == *s ) {
p++;
s++;
}
info("matched len: %d == pattern len %d\n", (int)(p - e->pattern) , e->pattern_len);
if ( p - e->pattern == e->pattern_len ) {
return e;
}
*/
}
return NULL;
}
node * rtree_lookup(node * tree, char * path, int path_len) {
token_array * tokens = split_route_pattern(path, path_len);
str_array * tokens = split_route_pattern(path, path_len);
node * n = tree;
edge * e = NULL;
for ( int i = 0 ; i < tokens->len ; i++ ) {
e = node_find_edge(n, token_array_fetch(tokens, i) );
e = node_find_edge(n, str_array_fetch(tokens, i) );
if (!e) {
return NULL;
}
@ -282,25 +316,6 @@ node * node_create() {
}
node * rtree_insert_tokens(node * tree, token_array * tokens) {
node * n = tree;
edge * e = NULL;
for ( int i = 0 ; i < tokens->len ; i++ ) {
e = node_find_edge(n, token_array_fetch(tokens, i) );
if (e) {
n = e->child;
continue;
}
// insert node
node * child = node_create();
rtree_add_child(n, strdup(token_array_fetch(tokens,i)) , child);
n = child;
}
n->endpoint++;
return n;
}
node * rtree_insert_path(node *tree, char *route, void * route_ptr)
{
return rtree_insert_pathn(tree, route, strlen(route) , route_ptr);
@ -343,6 +358,7 @@ node * rtree_insert_pathn(node *tree, char *route, int route_len, void * route_p
rtree_add_child(n, strndup(route, route_len) , child);
info("edge not found, insert one: %s\n", route);
child->route_ptr = route_ptr;
child->endpoint++;
return child;
} else if ( dl == e->pattern_len ) { // fully-equal to the pattern of the edge
@ -389,15 +405,10 @@ node * rtree_insert_pathn(node *tree, char *route, int route_len, void * route_p
c2->endpoint++;
c2->route_ptr = route_ptr;
return c2;
} else if ( dl > 0 ) {
} else {
printf("unexpected condition.");
return NULL;
}
// token_array * t = split_route_pattern(route, strlen(route));
// return rtree_insert_tokens(tree, t);
// n->endpoint++;
return n;
}
@ -441,7 +452,7 @@ void edge_branch(edge *e, int dl) {
e->child->edge_len = 0;
e->child->endpoint--;
info("branched pattern: %s", e1->pattern);
info("branched pattern: %s\n", e1->pattern);
rtree_append_edge(e->child, e1);
c1->endpoint++;
@ -471,9 +482,11 @@ void edge_free(edge * e) {
void rtree_dump(node * n, int level) {
if ( n->edge_len ) {
if ( n->combined_pattern ) {
printf(" regexp: %s", n->combined_pattern);
printf(" regexp:%s", n->combined_pattern);
}
printf("\n");
printf(" endpoint:%d\n", n->endpoint);
for ( int i = 0 ; i < n->edge_len ; i++ ) {
edge * e = n->edges[i];
print_indent(level);
@ -491,3 +504,9 @@ void rtree_dump(node * n, int level) {
}
}
}
/*
char * node_trace(node * n) {
}
*/

View file

@ -11,15 +11,15 @@
#include "token.h"
token_array * token_array_create(int cap) {
token_array * list = (token_array*) malloc( sizeof(token_array) );
str_array * str_array_create(int cap) {
str_array * list = (str_array*) malloc( sizeof(str_array) );
list->len = 0;
list->cap = cap;
list->tokens = (char**) malloc( sizeof(char*) * cap);
return list;
}
void token_array_free(token_array *l) {
void str_array_free(str_array *l) {
for ( int i = 0; i < l->len ; i++ ) {
char * t = l->tokens[ i ];
free(t);
@ -27,19 +27,19 @@ void token_array_free(token_array *l) {
free(l);
}
bool token_array_is_full(token_array * l) {
bool str_array_is_full(str_array * l) {
return l->len >= l->cap;
}
bool token_array_resize(token_array *l, int new_cap) {
bool str_array_resize(str_array *l, int new_cap) {
l->tokens = realloc(l->tokens, sizeof(char**) * new_cap);
l->cap = new_cap;
return l->tokens != NULL;
}
bool token_array_append(token_array * l, char * token) {
if ( token_array_is_full(l) ) {
bool ret = token_array_resize(l, l->cap + 20);
bool str_array_append(str_array * l, char * token) {
if ( str_array_is_full(l) ) {
bool ret = str_array_resize(l, l->cap + 20);
if (ret == FALSE ) {
return FALSE;
}
@ -48,7 +48,7 @@ bool token_array_append(token_array * l, char * token) {
return TRUE;
}
void token_array_dump(token_array *l) {
void str_array_dump(str_array *l) {
printf("[");
for ( int i = 0; i < l->len ; i++ ) {
printf("\"%s\"", l->tokens[i] );
@ -79,10 +79,10 @@ void token_array_dump(token_array *l) {
*
* @return char**
*/
token_array * split_route_pattern(char *pattern, int pattern_len) {
str_array * split_route_pattern(char *pattern, int pattern_len) {
char *s1, *p = pattern;
token_array * token_array = token_array_create( 20 );
str_array * str_array = str_array_create( 20 );
s1 = p;
p++;
@ -97,20 +97,20 @@ token_array * split_route_pattern(char *pattern, int pattern_len) {
}
p++; // contains the '}'
// printf("==> %s\n", strndup(s1, p-s1) );
token_array_append(token_array, strndup(s1, p-s1) );
str_array_append(str_array, strndup(s1, p-s1) );
s1 = p;
continue;
}
else if ( *p == '/' ) {
// printf("==> %s\n", strndup(s1, p-s1) );
token_array_append(token_array, strndup(s1, p-s1) );
str_array_append(str_array, strndup(s1, p-s1) );
s1 = p;
}
p++;
}
if ( p-s1 > 0 ) {
token_array_append(token_array, strndup(s1, p-s1) );
str_array_append(str_array, strndup(s1, p-s1) );
}
return token_array;
return str_array;
}

View file

@ -1,9 +1,32 @@
#include <stdio.h>
#include <check.h>
#include <stdlib.h>
#include "str.h"
#include "node.h"
#include "token.h"
#include <sys/time.h>
#define MICRO_IN_SEC 1000000.00
#define SEC_IN_MIN 60
#define NUL '\0'
double microtime() {
struct timeval tp;
long sec = 0L;
double msec = 0.0;
char ret[100];
if (gettimeofday((struct timeval *) &tp, (NUL)) == 0) {
msec = (double) (tp.tv_usec / MICRO_IN_SEC);
sec = tp.tv_sec;
if (msec >= 1.0)
msec -= (long) msec;
return sec + msec;
}
return 0;
}
START_TEST (test_ltrim_slash)
{
fail_if( strcmp( ltrim_slash("/blog") , "blog" ) != 0 );
@ -42,11 +65,14 @@ END_TEST
START_TEST (test_compile)
{
token_array *t;
str_array *t;
node * n;
n = rtree_create(10);
match_entry * entry;
node *m;
edge *e ;
rtree_insert_pathn(n, "/zoo", strlen("/zoo"), NULL);
rtree_insert_pathn(n, "/foo", strlen("/foo"), NULL);
@ -55,43 +81,51 @@ START_TEST (test_compile)
fail_if( n->combined_pattern );
fail_if( NULL == node_find_edge_str(n, "/", strlen("/") ) );
#ifdef DEBUG
rtree_dump(n, 0);
#endif
rtree_insert_pathn(n, "/foo/{id}", strlen("/foo/{id}"), NULL);
rtree_insert_pathn(n, "/{id}", strlen("/{id}"), NULL);
rtree_compile(n);
rtree_compile(n); // test double compile
#ifdef DEBUG
rtree_dump(n, 0);
#endif
/*
fail_if(n->edges[0]->child->combined_pattern == NULL);
edge *e = node_find_edge_str(n, "/", strlen("/") );
e = node_find_edge_str(n, "/", strlen("/") );
fail_if( NULL == e );
*/
/*
printf( "%s\n", e->pattern );
printf( "%s\n", e->child->combined_pattern );
printf( "%s\n", n->edges[0]->child->combined_pattern);
printf( "%s\n", n->combined_pattern );
*/
node *m = rtree_match( e->child , "foo", strlen("foo") );
entry = calloc( sizeof(entry) , 1 );
m = rtree_match( n , "/foo", strlen("/foo"), entry);
fail_if( NULL == m );
m = rtree_match( n , "/foo", strlen("/foo") );
m = rtree_match( n , "/zoo", strlen("/zoo"), entry);
fail_if( NULL == m );
m = rtree_match( n , "/zoo", strlen("/zoo") );
m = rtree_match( n , "/bar", strlen("/bar"), entry);
fail_if( NULL == m );
m = rtree_match( n , "/bar", strlen("/bar") );
m = rtree_match( n , "/xxx", strlen("/xxx"), entry);
fail_if( NULL == m );
m = rtree_match( n , "/xxx", strlen("/xxx") );
m = rtree_match( n , "/foo/xxx", strlen("/foo/xxx"), entry);
fail_if( NULL == m );
m = rtree_match( n , "/foo/xxx", strlen("/foo/xxx") );
m = rtree_match( n , "/some_id", strlen("/some_id"), entry);
fail_if( NULL == m );
m = rtree_match( n , "/not_found", strlen("/not_found") );
fail_if( NULL == m ); // should be the node of "/"
ck_assert_int_eq( m->endpoint , 0 ); // should not be an endpoint
ck_assert_int_gt( m->endpoint , 0 ); // should not be an endpoint
}
END_TEST
@ -144,44 +178,33 @@ START_TEST (test_rtree_insert_pathn)
{
node * n = rtree_create(10);
// printf("Inserting /foo/bar\n");
rtree_insert_pathn(n, "/foo/bar", strlen("/foo/bar"), NULL);
info("Inserting /foo/bar\n");
rtree_insert_path(n, "/foo/bar", NULL);
// rtree_dump(n, 0);
// printf("Inserting /foo/zoo\n");
rtree_insert_pathn(n, "/foo/zoo", strlen("/foo/zoo"), NULL);
info("Inserting /foo/zoo\n");
rtree_insert_path(n, "/foo/zoo", NULL);
// rtree_dump(n, 0);
// printf("Inserting /f/id\n");
rtree_insert_pathn(n, "/f/id", strlen("/f/id") , NULL);
info("Inserting /f/id\n");
rtree_insert_path(n, "/f/id" , NULL);
// rtree_dump(n, 0);
// printf("Inserting /post/{id}\n");
info("Inserting /post/{id}\n");
rtree_insert_pathn(n, "/post/{id}", strlen("/post/{id}"), NULL);
// rtree_dump(n, 0);
// printf("Inserting /post/{handle}\n");
info("Inserting /post/{handle}\n");
rtree_insert_pathn(n, "/post/{handle}", strlen("/post/{handle}"), NULL);
// rtree_dump(n, 0);
// printf("Inserting /post/{handle}-{id}\n");
info("Inserting /post/{handle}-{id}\n");
rtree_insert_pathn(n, "/post/{handle}-{id}", strlen("/post/{handle}-{id}"), NULL);
rtree_compile(n);
// rtree_dump(n, 0);
/*
fail_if( rtree_lookup(n , "/a/jj/kk" , strlen("/a/jj/kk") ) == NULL );
fail_if( rtree_lookup(n , "/a/jj" , strlen("/a/jj") ) != NULL );
fail_if( rtree_lookup(n , "/a/jj/kk/ll" , strlen("/a/jj/kk/ll") ) != NULL );
fail_if( rtree_lookup(n, "/xxxx", strlen("xxxx") ) != NULL );
*/
// fail_if( node_find_edge(n, "/add") == NULL );
// fail_if( node_find_edge(n, "/bar") != NULL );
#ifdef DEBUG
rtree_dump(n, 0);
#endif
rtree_free(n);
}
END_TEST
@ -191,60 +214,431 @@ END_TEST
START_TEST (test_route_split)
{
token_array *t;
str_array *t;
t = split_route_pattern("/blog", strlen("/blog") );
fail_if( t == NULL );
token_array_dump(t);
token_array_free(t);
str_array_dump(t);
str_array_free(t);
t = split_route_pattern("/foo/{id}", strlen("/foo/{id}") );
fail_if( t == NULL );
token_array_dump(t);
str_array_dump(t);
fail_if( t->len != 2 );
token_array_free(t);
str_array_free(t);
t = split_route_pattern("/foo/bar/{id}", strlen("/foo/bar/{id}") );
fail_if( t == NULL );
token_array_dump(t);
str_array_dump(t);
fail_if( t->len != 3 );
token_array_free(t);
str_array_free(t);
t = split_route_pattern("/{title}", strlen("/{title}") );
fail_if( t == NULL );
token_array_dump(t);
str_array_dump(t);
fail_if( t->len != 1 );
token_array_free(t);
str_array_free(t);
t = split_route_pattern("/", strlen("/") );
fail_if( t == NULL );
token_array_dump(t);
str_array_dump(t);
fail_if( t->len != 1 );
token_array_free(t);
str_array_free(t);
}
END_TEST
START_TEST (test_token_array)
START_TEST (test_str_array)
{
token_array * l = token_array_create(3);
str_array * l = str_array_create(3);
fail_if( l == NULL );
fail_if( FALSE == token_array_append(l, strdup("abc") ) );
fail_if( FALSE == str_array_append(l, strdup("abc") ) );
fail_if( l->len != 1 );
fail_if( FALSE == token_array_append(l, strdup("foo") ) );
fail_if( FALSE == str_array_append(l, strdup("foo") ) );
fail_if( l->len != 2 );
fail_if( FALSE == token_array_append(l, strdup("bar") ) );
fail_if( FALSE == str_array_append(l, strdup("bar") ) );
fail_if( l->len != 3 );
fail_if( FALSE == token_array_append(l, strdup("zoo") ) );
fail_if( FALSE == str_array_append(l, strdup("zoo") ) );
fail_if( l->len != 4 );
fail_if( FALSE == token_array_resize(l, l->cap * 2) );
fail_if( FALSE == str_array_resize(l, l->cap * 2) );
str_array_free(l);
}
END_TEST
START_TEST(benchmark_str)
{
match_entry * entry = calloc( sizeof(entry) , 1 );
node * n = rtree_create(1);
rtree_insert_path(n, "/foo/bar/baz", NULL);
rtree_insert_path(n, "/foo/bar/qux", NULL);
rtree_insert_path(n, "/foo/bar/quux", NULL);
rtree_insert_path(n, "/foo/bar/corge", NULL);
rtree_insert_path(n, "/foo/bar/grault", NULL);
rtree_insert_path(n, "/foo/bar/garply", NULL);
rtree_insert_path(n, "/foo/baz/bar", NULL);
rtree_insert_path(n, "/foo/baz/qux", NULL);
rtree_insert_path(n, "/foo/baz/quux", NULL);
rtree_insert_path(n, "/foo/baz/corge", NULL);
rtree_insert_path(n, "/foo/baz/grault", NULL);
rtree_insert_path(n, "/foo/baz/garply", NULL);
rtree_insert_path(n, "/foo/qux/bar", NULL);
rtree_insert_path(n, "/foo/qux/baz", NULL);
rtree_insert_path(n, "/foo/qux/quux", NULL);
rtree_insert_path(n, "/foo/qux/corge", NULL);
rtree_insert_path(n, "/foo/qux/grault", NULL);
rtree_insert_path(n, "/foo/qux/garply", NULL);
rtree_insert_path(n, "/foo/quux/bar", NULL);
rtree_insert_path(n, "/foo/quux/baz", NULL);
rtree_insert_path(n, "/foo/quux/qux", NULL);
rtree_insert_path(n, "/foo/quux/corge", NULL);
rtree_insert_path(n, "/foo/quux/grault", NULL);
rtree_insert_path(n, "/foo/quux/garply", NULL);
rtree_insert_path(n, "/foo/corge/bar", NULL);
rtree_insert_path(n, "/foo/corge/baz", NULL);
rtree_insert_path(n, "/foo/corge/qux", NULL);
rtree_insert_path(n, "/foo/corge/quux", NULL);
rtree_insert_path(n, "/foo/corge/grault", NULL);
rtree_insert_path(n, "/foo/corge/garply", NULL);
rtree_insert_path(n, "/foo/grault/bar", NULL);
rtree_insert_path(n, "/foo/grault/baz", NULL);
rtree_insert_path(n, "/foo/grault/qux", NULL);
rtree_insert_path(n, "/foo/grault/quux", NULL);
rtree_insert_path(n, "/foo/grault/corge", NULL);
rtree_insert_path(n, "/foo/grault/garply", NULL);
rtree_insert_path(n, "/foo/garply/bar", NULL);
rtree_insert_path(n, "/foo/garply/baz", NULL);
rtree_insert_path(n, "/foo/garply/qux", NULL);
rtree_insert_path(n, "/foo/garply/quux", NULL);
rtree_insert_path(n, "/foo/garply/corge", NULL);
rtree_insert_path(n, "/foo/garply/grault", NULL);
rtree_insert_path(n, "/bar/foo/baz", NULL);
rtree_insert_path(n, "/bar/foo/qux", NULL);
rtree_insert_path(n, "/bar/foo/quux", NULL);
rtree_insert_path(n, "/bar/foo/corge", NULL);
rtree_insert_path(n, "/bar/foo/grault", NULL);
rtree_insert_path(n, "/bar/foo/garply", NULL);
rtree_insert_path(n, "/bar/baz/foo", NULL);
rtree_insert_path(n, "/bar/baz/qux", NULL);
rtree_insert_path(n, "/bar/baz/quux", NULL);
rtree_insert_path(n, "/bar/baz/corge", NULL);
rtree_insert_path(n, "/bar/baz/grault", NULL);
rtree_insert_path(n, "/bar/baz/garply", NULL);
rtree_insert_path(n, "/bar/qux/foo", NULL);
rtree_insert_path(n, "/bar/qux/baz", NULL);
rtree_insert_path(n, "/bar/qux/quux", NULL);
rtree_insert_path(n, "/bar/qux/corge", NULL);
rtree_insert_path(n, "/bar/qux/grault", NULL);
rtree_insert_path(n, "/bar/qux/garply", NULL);
rtree_insert_path(n, "/bar/quux/foo", NULL);
rtree_insert_path(n, "/bar/quux/baz", NULL);
rtree_insert_path(n, "/bar/quux/qux", NULL);
rtree_insert_path(n, "/bar/quux/corge", NULL);
rtree_insert_path(n, "/bar/quux/grault", NULL);
rtree_insert_path(n, "/bar/quux/garply", NULL);
rtree_insert_path(n, "/bar/corge/foo", NULL);
rtree_insert_path(n, "/bar/corge/baz", NULL);
rtree_insert_path(n, "/bar/corge/qux", NULL);
rtree_insert_path(n, "/bar/corge/quux", NULL);
rtree_insert_path(n, "/bar/corge/grault", NULL);
rtree_insert_path(n, "/bar/corge/garply", NULL);
rtree_insert_path(n, "/bar/grault/foo", NULL);
rtree_insert_path(n, "/bar/grault/baz", NULL);
rtree_insert_path(n, "/bar/grault/qux", NULL);
rtree_insert_path(n, "/bar/grault/quux", NULL);
rtree_insert_path(n, "/bar/grault/corge", NULL);
rtree_insert_path(n, "/bar/grault/garply", NULL);
rtree_insert_path(n, "/bar/garply/foo", NULL);
rtree_insert_path(n, "/bar/garply/baz", NULL);
rtree_insert_path(n, "/bar/garply/qux", NULL);
rtree_insert_path(n, "/bar/garply/quux", NULL);
rtree_insert_path(n, "/bar/garply/corge", NULL);
rtree_insert_path(n, "/bar/garply/grault", NULL);
rtree_insert_path(n, "/baz/foo/bar", NULL);
rtree_insert_path(n, "/baz/foo/qux", NULL);
rtree_insert_path(n, "/baz/foo/quux", NULL);
rtree_insert_path(n, "/baz/foo/corge", NULL);
rtree_insert_path(n, "/baz/foo/grault", NULL);
rtree_insert_path(n, "/baz/foo/garply", NULL);
rtree_insert_path(n, "/baz/bar/foo", NULL);
rtree_insert_path(n, "/baz/bar/qux", NULL);
rtree_insert_path(n, "/baz/bar/quux", NULL);
rtree_insert_path(n, "/baz/bar/corge", NULL);
rtree_insert_path(n, "/baz/bar/grault", NULL);
rtree_insert_path(n, "/baz/bar/garply", NULL);
rtree_insert_path(n, "/baz/qux/foo", NULL);
rtree_insert_path(n, "/baz/qux/bar", NULL);
rtree_insert_path(n, "/baz/qux/quux", NULL);
rtree_insert_path(n, "/baz/qux/corge", NULL);
rtree_insert_path(n, "/baz/qux/grault", NULL);
rtree_insert_path(n, "/baz/qux/garply", NULL);
rtree_insert_path(n, "/baz/quux/foo", NULL);
rtree_insert_path(n, "/baz/quux/bar", NULL);
rtree_insert_path(n, "/baz/quux/qux", NULL);
rtree_insert_path(n, "/baz/quux/corge", NULL);
rtree_insert_path(n, "/baz/quux/grault", NULL);
rtree_insert_path(n, "/baz/quux/garply", NULL);
rtree_insert_path(n, "/baz/corge/foo", NULL);
rtree_insert_path(n, "/baz/corge/bar", NULL);
rtree_insert_path(n, "/baz/corge/qux", NULL);
rtree_insert_path(n, "/baz/corge/quux", NULL);
rtree_insert_path(n, "/baz/corge/grault", NULL);
rtree_insert_path(n, "/baz/corge/garply", NULL);
rtree_insert_path(n, "/baz/grault/foo", NULL);
rtree_insert_path(n, "/baz/grault/bar", NULL);
rtree_insert_path(n, "/baz/grault/qux", NULL);
rtree_insert_path(n, "/baz/grault/quux", NULL);
rtree_insert_path(n, "/baz/grault/corge", NULL);
rtree_insert_path(n, "/baz/grault/garply", NULL);
rtree_insert_path(n, "/baz/garply/foo", NULL);
rtree_insert_path(n, "/baz/garply/bar", NULL);
rtree_insert_path(n, "/baz/garply/qux", NULL);
rtree_insert_path(n, "/baz/garply/quux", NULL);
rtree_insert_path(n, "/baz/garply/corge", NULL);
rtree_insert_path(n, "/baz/garply/grault", NULL);
rtree_insert_path(n, "/qux/foo/bar", NULL);
rtree_insert_path(n, "/qux/foo/baz", NULL);
rtree_insert_path(n, "/qux/foo/quux", NULL);
rtree_insert_path(n, "/qux/foo/corge", NULL);
rtree_insert_path(n, "/qux/foo/grault", NULL);
rtree_insert_path(n, "/qux/foo/garply", NULL);
rtree_insert_path(n, "/qux/bar/foo", NULL);
rtree_insert_path(n, "/qux/bar/baz", NULL);
rtree_insert_path(n, "/qux/bar/quux", NULL);
rtree_insert_path(n, "/qux/bar/corge", (void*) 999);
rtree_insert_path(n, "/qux/bar/grault", NULL);
rtree_insert_path(n, "/qux/bar/garply", NULL);
rtree_insert_path(n, "/qux/baz/foo", NULL);
rtree_insert_path(n, "/qux/baz/bar", NULL);
rtree_insert_path(n, "/qux/baz/quux", NULL);
rtree_insert_path(n, "/qux/baz/corge", NULL);
rtree_insert_path(n, "/qux/baz/grault", NULL);
rtree_insert_path(n, "/qux/baz/garply", NULL);
rtree_insert_path(n, "/qux/quux/foo", NULL);
rtree_insert_path(n, "/qux/quux/bar", NULL);
rtree_insert_path(n, "/qux/quux/baz", NULL);
rtree_insert_path(n, "/qux/quux/corge", NULL);
rtree_insert_path(n, "/qux/quux/grault", NULL);
rtree_insert_path(n, "/qux/quux/garply", NULL);
rtree_insert_path(n, "/qux/corge/foo", NULL);
rtree_insert_path(n, "/qux/corge/bar", NULL);
rtree_insert_path(n, "/qux/corge/baz", NULL);
rtree_insert_path(n, "/qux/corge/quux", NULL);
rtree_insert_path(n, "/qux/corge/grault", NULL);
rtree_insert_path(n, "/qux/corge/garply", NULL);
rtree_insert_path(n, "/qux/grault/foo", NULL);
rtree_insert_path(n, "/qux/grault/bar", NULL);
rtree_insert_path(n, "/qux/grault/baz", NULL);
rtree_insert_path(n, "/qux/grault/quux", NULL);
rtree_insert_path(n, "/qux/grault/corge", NULL);
rtree_insert_path(n, "/qux/grault/garply", NULL);
rtree_insert_path(n, "/qux/garply/foo", NULL);
rtree_insert_path(n, "/qux/garply/bar", NULL);
rtree_insert_path(n, "/qux/garply/baz", NULL);
rtree_insert_path(n, "/qux/garply/quux", NULL);
rtree_insert_path(n, "/qux/garply/corge", NULL);
rtree_insert_path(n, "/qux/garply/grault", NULL);
rtree_insert_path(n, "/quux/foo/bar", NULL);
rtree_insert_path(n, "/quux/foo/baz", NULL);
rtree_insert_path(n, "/quux/foo/qux", NULL);
rtree_insert_path(n, "/quux/foo/corge", NULL);
rtree_insert_path(n, "/quux/foo/grault", NULL);
rtree_insert_path(n, "/quux/foo/garply", NULL);
rtree_insert_path(n, "/quux/bar/foo", NULL);
rtree_insert_path(n, "/quux/bar/baz", NULL);
rtree_insert_path(n, "/quux/bar/qux", NULL);
rtree_insert_path(n, "/quux/bar/corge", NULL);
rtree_insert_path(n, "/quux/bar/grault", NULL);
rtree_insert_path(n, "/quux/bar/garply", NULL);
rtree_insert_path(n, "/quux/baz/foo", NULL);
rtree_insert_path(n, "/quux/baz/bar", NULL);
rtree_insert_path(n, "/quux/baz/qux", NULL);
rtree_insert_path(n, "/quux/baz/corge", NULL);
rtree_insert_path(n, "/quux/baz/grault", NULL);
rtree_insert_path(n, "/quux/baz/garply", NULL);
rtree_insert_path(n, "/quux/qux/foo", NULL);
rtree_insert_path(n, "/quux/qux/bar", NULL);
rtree_insert_path(n, "/quux/qux/baz", NULL);
rtree_insert_path(n, "/quux/qux/corge", NULL);
rtree_insert_path(n, "/quux/qux/grault", NULL);
rtree_insert_path(n, "/quux/qux/garply", NULL);
rtree_insert_path(n, "/quux/corge/foo", NULL);
rtree_insert_path(n, "/quux/corge/bar", NULL);
rtree_insert_path(n, "/quux/corge/baz", NULL);
rtree_insert_path(n, "/quux/corge/qux", NULL);
rtree_insert_path(n, "/quux/corge/grault", NULL);
rtree_insert_path(n, "/quux/corge/garply", NULL);
rtree_insert_path(n, "/quux/grault/foo", NULL);
rtree_insert_path(n, "/quux/grault/bar", NULL);
rtree_insert_path(n, "/quux/grault/baz", NULL);
rtree_insert_path(n, "/quux/grault/qux", NULL);
rtree_insert_path(n, "/quux/grault/corge", NULL);
rtree_insert_path(n, "/quux/grault/garply", NULL);
rtree_insert_path(n, "/quux/garply/foo", NULL);
rtree_insert_path(n, "/quux/garply/bar", NULL);
rtree_insert_path(n, "/quux/garply/baz", NULL);
rtree_insert_path(n, "/quux/garply/qux", NULL);
rtree_insert_path(n, "/quux/garply/corge", NULL);
rtree_insert_path(n, "/quux/garply/grault", NULL);
rtree_insert_path(n, "/corge/foo/bar", NULL);
rtree_insert_path(n, "/corge/foo/baz", NULL);
rtree_insert_path(n, "/corge/foo/qux", NULL);
rtree_insert_path(n, "/corge/foo/quux", NULL);
rtree_insert_path(n, "/corge/foo/grault", NULL);
rtree_insert_path(n, "/corge/foo/garply", NULL);
rtree_insert_path(n, "/corge/bar/foo", NULL);
rtree_insert_path(n, "/corge/bar/baz", NULL);
rtree_insert_path(n, "/corge/bar/qux", NULL);
rtree_insert_path(n, "/corge/bar/quux", NULL);
rtree_insert_path(n, "/corge/bar/grault", NULL);
rtree_insert_path(n, "/corge/bar/garply", NULL);
rtree_insert_path(n, "/corge/baz/foo", NULL);
rtree_insert_path(n, "/corge/baz/bar", NULL);
rtree_insert_path(n, "/corge/baz/qux", NULL);
rtree_insert_path(n, "/corge/baz/quux", NULL);
rtree_insert_path(n, "/corge/baz/grault", NULL);
rtree_insert_path(n, "/corge/baz/garply", NULL);
rtree_insert_path(n, "/corge/qux/foo", NULL);
rtree_insert_path(n, "/corge/qux/bar", NULL);
rtree_insert_path(n, "/corge/qux/baz", NULL);
rtree_insert_path(n, "/corge/qux/quux", NULL);
rtree_insert_path(n, "/corge/qux/grault", NULL);
rtree_insert_path(n, "/corge/qux/garply", NULL);
rtree_insert_path(n, "/corge/quux/foo", NULL);
rtree_insert_path(n, "/corge/quux/bar", NULL);
rtree_insert_path(n, "/corge/quux/baz", NULL);
rtree_insert_path(n, "/corge/quux/qux", NULL);
rtree_insert_path(n, "/corge/quux/grault", NULL);
rtree_insert_path(n, "/corge/quux/garply", NULL);
rtree_insert_path(n, "/corge/grault/foo", NULL);
rtree_insert_path(n, "/corge/grault/bar", NULL);
rtree_insert_path(n, "/corge/grault/baz", NULL);
rtree_insert_path(n, "/corge/grault/qux", NULL);
rtree_insert_path(n, "/corge/grault/quux", NULL);
rtree_insert_path(n, "/corge/grault/garply", NULL);
rtree_insert_path(n, "/corge/garply/foo", NULL);
rtree_insert_path(n, "/corge/garply/bar", NULL);
rtree_insert_path(n, "/corge/garply/baz", NULL);
rtree_insert_path(n, "/corge/garply/qux", NULL);
rtree_insert_path(n, "/corge/garply/quux", NULL);
rtree_insert_path(n, "/corge/garply/grault", NULL);
rtree_insert_path(n, "/grault/foo/bar", NULL);
rtree_insert_path(n, "/grault/foo/baz", NULL);
rtree_insert_path(n, "/grault/foo/qux", NULL);
rtree_insert_path(n, "/grault/foo/quux", NULL);
rtree_insert_path(n, "/grault/foo/corge", NULL);
rtree_insert_path(n, "/grault/foo/garply", NULL);
rtree_insert_path(n, "/grault/bar/foo", NULL);
rtree_insert_path(n, "/grault/bar/baz", NULL);
rtree_insert_path(n, "/grault/bar/qux", NULL);
rtree_insert_path(n, "/grault/bar/quux", NULL);
rtree_insert_path(n, "/grault/bar/corge", NULL);
rtree_insert_path(n, "/grault/bar/garply", NULL);
rtree_insert_path(n, "/grault/baz/foo", NULL);
rtree_insert_path(n, "/grault/baz/bar", NULL);
rtree_insert_path(n, "/grault/baz/qux", NULL);
rtree_insert_path(n, "/grault/baz/quux", NULL);
rtree_insert_path(n, "/grault/baz/corge", NULL);
rtree_insert_path(n, "/grault/baz/garply", NULL);
rtree_insert_path(n, "/grault/qux/foo", NULL);
rtree_insert_path(n, "/grault/qux/bar", NULL);
rtree_insert_path(n, "/grault/qux/baz", NULL);
rtree_insert_path(n, "/grault/qux/quux", NULL);
rtree_insert_path(n, "/grault/qux/corge", NULL);
rtree_insert_path(n, "/grault/qux/garply", NULL);
rtree_insert_path(n, "/grault/quux/foo", NULL);
rtree_insert_path(n, "/grault/quux/bar", NULL);
rtree_insert_path(n, "/grault/quux/baz", NULL);
rtree_insert_path(n, "/grault/quux/qux", NULL);
rtree_insert_path(n, "/grault/quux/corge", NULL);
rtree_insert_path(n, "/grault/quux/garply", NULL);
rtree_insert_path(n, "/grault/corge/foo", NULL);
rtree_insert_path(n, "/grault/corge/bar", NULL);
rtree_insert_path(n, "/grault/corge/baz", NULL);
rtree_insert_path(n, "/grault/corge/qux", NULL);
rtree_insert_path(n, "/grault/corge/quux", NULL);
rtree_insert_path(n, "/grault/corge/garply", NULL);
rtree_insert_path(n, "/grault/garply/foo", NULL);
rtree_insert_path(n, "/grault/garply/bar", NULL);
rtree_insert_path(n, "/grault/garply/baz", NULL);
rtree_insert_path(n, "/grault/garply/qux", NULL);
rtree_insert_path(n, "/grault/garply/quux", NULL);
rtree_insert_path(n, "/grault/garply/corge", NULL);
rtree_insert_path(n, "/garply/foo/bar", NULL);
rtree_insert_path(n, "/garply/foo/baz", NULL);
rtree_insert_path(n, "/garply/foo/qux", NULL);
rtree_insert_path(n, "/garply/foo/quux", NULL);
rtree_insert_path(n, "/garply/foo/corge", NULL);
rtree_insert_path(n, "/garply/foo/grault", NULL);
rtree_insert_path(n, "/garply/bar/foo", NULL);
rtree_insert_path(n, "/garply/bar/baz", NULL);
rtree_insert_path(n, "/garply/bar/qux", NULL);
rtree_insert_path(n, "/garply/bar/quux", NULL);
rtree_insert_path(n, "/garply/bar/corge", NULL);
rtree_insert_path(n, "/garply/bar/grault", NULL);
rtree_insert_path(n, "/garply/baz/foo", NULL);
rtree_insert_path(n, "/garply/baz/bar", NULL);
rtree_insert_path(n, "/garply/baz/qux", NULL);
rtree_insert_path(n, "/garply/baz/quux", NULL);
rtree_insert_path(n, "/garply/baz/corge", NULL);
rtree_insert_path(n, "/garply/baz/grault", NULL);
rtree_insert_path(n, "/garply/qux/foo", NULL);
rtree_insert_path(n, "/garply/qux/bar", NULL);
rtree_insert_path(n, "/garply/qux/baz", NULL);
rtree_insert_path(n, "/garply/qux/quux", NULL);
rtree_insert_path(n, "/garply/qux/corge", NULL);
rtree_insert_path(n, "/garply/qux/grault", NULL);
rtree_insert_path(n, "/garply/quux/foo", NULL);
rtree_insert_path(n, "/garply/quux/bar", NULL);
rtree_insert_path(n, "/garply/quux/baz", NULL);
rtree_insert_path(n, "/garply/quux/qux", NULL);
rtree_insert_path(n, "/garply/quux/corge", NULL);
rtree_insert_path(n, "/garply/quux/grault", NULL);
rtree_insert_path(n, "/garply/corge/foo", NULL);
rtree_insert_path(n, "/garply/corge/bar", NULL);
rtree_insert_path(n, "/garply/corge/baz", NULL);
rtree_insert_path(n, "/garply/corge/qux", NULL);
rtree_insert_path(n, "/garply/corge/quux", NULL);
rtree_insert_path(n, "/garply/corge/grault", NULL);
rtree_insert_path(n, "/garply/grault/foo", NULL);
rtree_insert_path(n, "/garply/grault/bar", NULL);
rtree_insert_path(n, "/garply/grault/baz", NULL);
rtree_insert_path(n, "/garply/grault/qux", NULL);
rtree_insert_path(n, "/garply/grault/quux", NULL);
rtree_insert_path(n, "/garply/grault/corge", NULL);
rtree_compile(n);
// rtree_dump(n, 0);
// match_entry *entry = calloc( sizeof(entry) , 1 );
node *m;
m = rtree_match(n , "/qux/bar/corge", strlen("/qux/bar/corge"), NULL);
fail_if( m == NULL );
// rtree_dump( m, 0 );
ck_assert_int_eq( (int) m->route_ptr, 999 );
printf("Benchmarking...\n");
double s = microtime();
unsigned int N = 5000000;
for (int i = 0; i < 5000000 ; i++ ) {
rtree_match(n , "/qux/bar/corge", strlen("/qux/bar/corge"), NULL);
}
double e = microtime();
printf("%.2f i/sec\n", e - s / N );
printf("%lf seconds\n", e - s );
FILE *fp = fopen("bench_str.csv", "a+");
fprintf(fp, "%.2f,\"%s\"\n", e - s / N, "using strcmp" );
fclose(fp);
token_array_free(l);
}
END_TEST
@ -253,7 +647,7 @@ Suite* r3_suite (void) {
TCase *tcase = tcase_create("testcase");
tcase_add_test(tcase, test_route_split);
tcase_add_test(tcase, test_token_array);
tcase_add_test(tcase, test_str_array);
tcase_add_test(tcase, test_ltrim_slash);
tcase_add_test(tcase, test_node_construct_uniq);
tcase_add_test(tcase, test_node_find_edge);
@ -261,6 +655,8 @@ Suite* r3_suite (void) {
tcase_add_test(tcase, test_compile_slug);
tcase_add_test(tcase, test_compile);
tcase_add_test(tcase, benchmark_str);
suite_add_tcase(suite, tcase);
return suite;