Compare commits

...

24 commits

Author SHA1 Message Date
c9s
0f5ebed73c Merge branch 'master' into feature/stats 2014-05-23 23:39:58 +08:00
c9s
0b499c9158 append new records 2014-05-23 23:28:50 +08:00
c9s
76e4b15787 Merge branch 'master' into feature/stats
Conflicts:
	bench.html
	bench_str.csv
	config.h
	config.h.in
	include/r3.h
	src/node.c
2014-05-23 23:27:10 +08:00
c9s
546fcb14af let tooltip display flags 2014-05-22 23:14:46 +08:00
c9s
faaaeb5f90 Merge branch 'master' into feature/stats
Conflicts:
	config.h
	tests/bench.c
	tests/bench.h
	tests/bench_str.csv
	tests/check_tree.c
2014-05-22 22:31:48 +08:00
c9s
8471f42579 edge alignment 2014-05-22 20:26:27 +08:00
c9s
3cbffb645c /= 100.0 2014-05-22 19:42:37 +08:00
c9s
1563bd5a78 fix syntax 2014-05-22 19:24:04 +08:00
c9s
adbe71d336 Add _root node for mutex/spin 2014-05-22 19:20:21 +08:00
c9s
d73a3aa89a Add a basic feedback system 2014-05-22 17:22:54 +08:00
c9s
a4378fdaf2 Add test_feedback 2014-05-22 17:07:02 +08:00
c9s
3121937da5 Add bench_duration function 2014-05-22 17:03:33 +08:00
c9s
c421bea11f free tree at the end of benchmarking 2014-05-22 17:00:22 +08:00
c9s
5ada611182 refactor Benchmark related macros 2014-05-22 16:59:40 +08:00
c9s
ba270b5948 setting up parent and child. 2014-05-22 16:53:52 +08:00
c9s
24aaa881b1 set node's parent edge 2014-05-22 16:44:56 +08:00
c9s
595dadba15 Merge branch 'master' into feature/stats
Conflicts:
	config.h
	configure.ac
	tests/bench_str.csv
2014-05-22 16:41:46 +08:00
c9s
d6b2e52567 Add hits, score fields to edge struct 2014-05-22 16:37:53 +08:00
c9s
2b331ecc8f use uint8_t for endpoint 2014-05-22 16:33:41 +08:00
c9s
21a8c0c891 include config.h in r3.h 2014-05-22 16:32:06 +08:00
c9s
a5035ad962 safer uint define 2014-05-22 16:30:09 +08:00
c9s
3500e19316 include stdint.h 2014-05-22 16:29:22 +08:00
c9s
58b74b9126 check stdint.h header 2014-05-22 16:26:55 +08:00
c9s
f8154b23e9 Add --enable-stats option 2014-05-22 16:24:24 +08:00
8 changed files with 315 additions and 45 deletions

View file

@ -70,10 +70,43 @@
}, },
tooltip: { tooltip: {
// headerFormat: '<span style="font-size: 10px">{point.key}: </span><br/>',
formatter: function() {
var s = '';
var comment = this.points[1].point.comment;
// new Date(this.x) + ':';
if (comment) {
s += '<span style="font-size: 10px;">';
s += comment;
s += '</span><br/>';
}
$.each(this.points, function(i, point) {
s += '<span style="color:' + point.series.color + '">\u25CF</span> ' + point.series.name + ': <b>' + point.y + '</b><br/>';
});
return s;
},
shared: true, shared: true,
crosshairs: true crosshairs: true
}, },
/*
tooltip: {
formatter: function() {
var s = '';
$.each(this.points, function(i, point) {
s += point.series.name +': '+ point.y + '<br/>';
});
if (this.points[1] && this.points[1].comment) {
s += '<b>'+ this.points[1].comment +'</b>';
}
return s;
},
shared: true
},
*/
plotOptions: { plotOptions: {
/* /*
area: { area: {
@ -148,19 +181,23 @@
var lines = data.split(/\n/); var lines = data.split(/\n/);
$(lines).each(function(i,line) { $(lines).each(function(i,line) {
/*
{ marker: {
fillColor: '#FF0000',
lineWidth: 3,
lineColor: "#FF0000" // inherit from series
}
*/
var columns = line.split(/,/); var columns = line.split(/,/);
var a; var commentText = columns[5];
a = parseInt(columns[1]); for (var i = 1; i < 5; i++ ) {
options.series[0].data.push(a || 0); var a = parseInt(columns[i]);
var args = a ?
a = parseInt(columns[2]); (commentText ? { y: a, comment: commentText } : a)
options.series[1].data.push(a || 0); : 0;
options.series[i-1].data.push(args);
a = parseInt(columns[3]); }
options.series[2].data.push(a || 0);
a = parseInt(columns[4]);
options.series[3].data.push(a || 0);
}); });
$('#chart').highcharts(options); $('#chart').highcharts(options);

View file

@ -443,6 +443,23 @@
1400668574,13632260.72 1400668574,13632260.72
1400681414,10832905.89 1400681414,10832905.89
1400685490,13185955.87 1400685490,13185955.87
1400748100,12609470.07
1400748288,13317009.48
1400748727,12973679.22
1400748826,12902583.84
1400748965,13584323.91
1400749175,13518288.33
1400749320,13445606.30
1400749326,13242705.99
1400749599,13245418.70
1400749614,12494314.81
1400749643,12690632.63
1400750350,10391028.46
1400750424,9445761.22
1400750472,9248611.74
1400750479,10757562.36
1400750512,10126746.58
1400750536,10568568.26
1400762875,10472029.42 1400762875,10472029.42
1400764426,10066458.45,1590373.41 1400764426,10066458.45,1590373.41
1400765068,10657617.64,2131810.12 1400765068,10657617.64,2131810.12
@ -511,3 +528,11 @@
1400837774,11190990.08,4331119.44,45590.26,2587281.10 1400837774,11190990.08,4331119.44,45590.26,2587281.10
1400837785,10306507.50,3909290.89,47662.55,2827471.10 1400837785,10306507.50,3909290.89,47662.55,2827471.10
1400837797,10323334.38,4221122.48,55924.05,2294463.55 1400837797,10323334.38,4221122.48,55924.05,2294463.55
1400858847,10663450.41,4674634.54,66576.25,2653715.59
1400858857,10336003.37,4496145.54,59074.70,2607583.19
1400858869,9640828.18,4607189.58,66576.25,2268341.79
1400858880,10959344.32,4114165.27,41943.04,2405089.57
1400858891,9456420.72,4254882.18,33554.43,2770969.36
1400858902,10904696.64,3989404.21,72315.59,2410755.81
1400858913,9379941.50,4385508.67,49932.19,2595906.55
1400858923,10653302.72,4655704.49,55188.21,2677379.49

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

118
config.h.in Normal file
View file

@ -0,0 +1,118 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* "whether graphviz is enable" */
#undef ENABLE_GRAPHVIZ
/* "whether statistics is enable" */
#undef ENABLE_STATS
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <jemalloc/jemalloc.h> header file. */
#undef HAVE_JEMALLOC_JEMALLOC_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you have the PATH_MAX macro. */
#undef USE_JEMALLOC
/* Version number of package */
#undef VERSION
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View file

@ -7,7 +7,8 @@ LT_INIT
AC_PROG_CC AC_PROG_CC
AC_PROG_CC_STDC AC_PROG_CC_STDC
# AM_PATH_CHECK() AC_CHECK_HEADERS([stdlib.h string.h sys/time.h stdint.h])
PKG_CHECK_MODULES(CHECK,[check >= 0.9.4],:,[ PKG_CHECK_MODULES(CHECK,[check >= 0.9.4],:,[
ifdef([AM_PATH_CHECK], ifdef([AM_PATH_CHECK],
[AM_PATH_CHECK(,[have_check="yes"])], [AM_PATH_CHECK(,[have_check="yes"])],
@ -16,8 +17,6 @@ PKG_CHECK_MODULES(CHECK,[check >= 0.9.4],:,[
]) ])
AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes") AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")
AC_CHECK_HEADERS([stdlib.h string.h sys/time.h])
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE AC_C_INLINE
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
@ -31,23 +30,10 @@ AC_CHECK_FUNCS([gettimeofday memset strchr strdup strndup strstr])
PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG
AC_ARG_ENABLE(graphviz,
AS_HELP_STRING([--enable-graphviz],
[enable graphviz support]),
, enable_graphviz=unset)
if test "x$enable_graphviz" != "xunset" ; then
PKG_CHECK_MODULES(GVC_DEPS, [libgvc])
AC_SUBST(GVC_DEPS_CFLAGS)
AC_SUBST(GVC_DEPS_LIBS)
fi
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug],
[enable debug]),
, enable_debug=unset)
AC_ARG_WITH([malloc],
AS_HELP_STRING([--without-malloc], [Use the default malloc])) AC_ARG_WITH([malloc], AS_HELP_STRING([--without-malloc], [Use the default malloc]))
AS_IF([test "x$with_malloc" == "xjemalloc"], AS_IF([test "x$with_malloc" == "xjemalloc"],
[AC_CHECK_HEADERS([jemalloc/jemalloc.h], [ [AC_CHECK_HEADERS([jemalloc/jemalloc.h], [
@ -77,16 +63,32 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <jemalloc/jemalloc.h>]],
) )
fi fi
AM_CONDITIONAL(USE_JEMALLOC, test "x$have_jemalloc" = "xyes") AM_CONDITIONAL(USE_JEMALLOC, test "x$have_jemalloc" = "xyes")
AM_CONDITIONAL(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes")
# AM_CONDITIONAL(USE_JEMALLOC, test "x$found_jemalloc" = "xyes") AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [enable debug]), [],[enable_debug=unset])
# AC_DEFINE(USE_JEMALLOC, test "x$found_jemalloc" = "xyes" , "use jemalloc")
AM_CONDITIONAL(ENABLE_DEBUG, test "x$enable_debug" = "xyes") AM_CONDITIONAL(ENABLE_DEBUG, test "x$enable_debug" = "xyes")
AC_ARG_ENABLE(graphviz,
AS_HELP_STRING([--enable-graphviz],
[enable graphviz support]),
, enable_graphviz=unset)
if test "x$enable_graphviz" != "xunset" ; then
PKG_CHECK_MODULES(GVC_DEPS, [libgvc])
AC_SUBST(GVC_DEPS_CFLAGS)
AC_SUBST(GVC_DEPS_LIBS)
fi
AM_CONDITIONAL(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes") AM_CONDITIONAL(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes")
AC_DEFINE(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes", "whether graphviz is enable") AC_DEFINE(ENABLE_GRAPHVIZ, test "x$enable_graphviz" = "xyes", "whether graphviz is enable")
PKG_CHECK_MODULES(DEPS, [libpcre check]) AC_ARG_ENABLE(stats, AS_HELP_STRING([--enable-stats], [enable statistics]), [] ,[enable_stats=unset])
AC_DEFINE(ENABLE_STATS, test "x$enable_stats" = "xyes", "whether statistics is enable")
PKG_CHECK_MODULES(DEPS, [libpcre])
AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_CFLAGS)
AC_SUBST(DEPS_LIBS) AC_SUBST(DEPS_LIBS)
AC_CONFIG_FILES([ AC_CONFIG_FILES([

View file

@ -15,27 +15,40 @@
#include "r3_define.h" #include "r3_define.h"
#include "str_array.h" #include "str_array.h"
#include "config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
#endif
#define node_edge_pattern(node,i) node->edges[i]->pattern #define node_edge_pattern(node,i) node->edges[i]->pattern
#define node_edge_pattern_len(node,i) node->edges[i]->pattern_len #define node_edge_pattern_len(node,i) node->edges[i]->pattern_len
struct _root;
struct _edge; struct _edge;
struct _node; struct _node;
struct _route; struct _route;
typedef struct _edge edge; typedef struct _edge edge;
typedef struct _node node; typedef struct _node node;
typedef struct _route route; typedef struct _route route;
typedef struct _root root;
struct _root {
};
struct _node { struct _node {
edge ** edges; edge ** edges;
route ** routes; route ** routes;
int edge_len; edge * parent_edge;
int edge_cap; uint32_t edge_len;
int route_len; uint32_t edge_cap;
int route_cap; uint32_t route_len;
int endpoint; uint32_t route_cap;
/** compile-time variables here.... **/ /** compile-time variables here.... **/
@ -50,14 +63,20 @@ struct _node {
*/ */
void * data; void * data;
uint8_t endpoint;
}; };
struct _edge { struct _edge {
/* the child node */
node * child;
/* the parent node */
node * parent;
char * pattern; char * pattern;
int pattern_len; int pattern_len;
int opcode; int opcode;
bool has_slug; float score;
node * child; bool has_slug:1;
}; };
typedef struct { typedef struct {
@ -167,6 +186,8 @@ void r3_route_free(route * route);
route * r3_tree_match_route(const node *n, match_entry * entry); route * r3_tree_match_route(const node *n, match_entry * entry);
void r3_tree_feedback(node *tree, node *end);
#define METHOD_GET 2 #define METHOD_GET 2
#define METHOD_POST 2<<1 #define METHOD_POST 2<<1
#define METHOD_PUT 2<<2 #define METHOD_PUT 2<<2

View file

@ -30,6 +30,14 @@ edge * r3_edge_create(char * pattern, int pattern_len, node * child) {
e->pattern_len = pattern_len; e->pattern_len = pattern_len;
e->opcode = 0; e->opcode = 0;
e->child = child; e->child = child;
e->parent = NULL;
// update childs parent edge
child->parent_edge = e;
// default stats
// e->hits = 0;
e->score = 0;
return e; return e;
} }
@ -56,6 +64,8 @@ node * r3_edge_branch(edge *e, int dl) {
// the suffix edge of the leaf // the suffix edge of the leaf
new_child = r3_tree_create(3); new_child = r3_tree_create(3);
s1_len = e->pattern_len - dl; s1_len = e->pattern_len - dl;
/* create the parent edge of new child */
e1 = r3_edge_create(zstrndup(s1, s1_len), s1_len, new_child); e1 = r3_edge_create(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.

View file

@ -45,6 +45,8 @@ node * r3_tree_create(int cap) {
n->edge_len = 0; n->edge_len = 0;
n->edge_cap = cap; n->edge_cap = cap;
n->parent_edge = NULL;
n->routes = NULL; n->routes = NULL;
n->route_len = 0; n->route_len = 0;
n->route_cap = 0; n->route_cap = 0;
@ -95,6 +97,26 @@ edge * r3_node_connectl(node * n, char * pat, int len, int dupl, node *child) {
return e; return e;
} }
void r3_tree_feedback(node *tree, node *end) {
edge * e = end->parent_edge;
node * p = e->parent;
while( p && e ) {
e->score += 0.1;
if (e->score > 100) {
for (int i = 0 ; i < p->edge_len ; i++ ) {
if ( p->edges[i]->score > 0 ) {
p->edges[i]->score /= 100.0;
}
}
}
e = p->parent_edge;
p = e ? e->parent : NULL;
}
}
void r3_node_append_edge(node *n, edge *e) { void r3_node_append_edge(node *n, edge *e) {
if (n->edges == NULL) { if (n->edges == NULL) {
n->edge_cap = 3; n->edge_cap = 3;
@ -107,6 +129,8 @@ void r3_node_append_edge(node *n, edge *e) {
n->edges = p; n->edges = p;
} }
} }
// when append new edge, we update the parent node of the edge.
e->parent = n;
n->edges[ n->edge_len++ ] = e; n->edges[ n->edge_len++ ] = e;
} }
@ -408,6 +432,8 @@ node * r3_node_create() {
n->edge_len = 0; n->edge_len = 0;
n->edge_cap = 0; n->edge_cap = 0;
n->parent_edge = NULL;
n->routes = NULL; n->routes = NULL;
n->route_len = 0; n->route_len = 0;
n->route_cap = 0; n->route_cap = 0;
@ -636,6 +662,8 @@ void r3_tree_dump(node * n, int level) {
print_indent(level + 1); print_indent(level + 1);
printf("|-\"%s\"", e->pattern); printf("|-\"%s\"", e->pattern);
// printf(" hits:%lld score:%.1f ", e->hits, e->score);
printf(" score:%.1f ", e->score);
if (e->opcode ) { if (e->opcode ) {
printf(" opcode:%d", e->opcode); printf(" opcode:%d", e->opcode);
} }

View file

@ -361,6 +361,34 @@ START_TEST(test_insert_route)
END_TEST END_TEST
START_TEST(test_feedback)
{
node * t = r3_tree_create(1);
r3_tree_insert_path(t, "/foo/bar/baz", NULL);
r3_tree_insert_path(t, "/foo/grault/bar", NULL);
r3_tree_insert_path(t, "/garply/corge/grault", NULL);
r3_tree_compile(t);
node * m1 = r3_tree_match(t, "/foo/grault/bar", NULL);
node * m2 = r3_tree_match(t, "/garply/corge/grault", NULL);
ck_assert(m1 != NULL);
ck_assert(m2 != NULL);
for ( int i = 0 ; i < 120 ; i++ ) {
r3_tree_feedback(t, m1);
}
for ( int i = 0 ; i < 200 ; i++ ) {
r3_tree_feedback(t, m2);
}
r3_tree_dump(t, 0);
r3_tree_free(t);
}
END_TEST
Suite* r3_suite (void) { Suite* r3_suite (void) {
Suite *suite = suite_create("blah"); Suite *suite = suite_create("blah");
@ -379,6 +407,7 @@ Suite* r3_suite (void) {
tcase_add_test(tcase, test_pcre_patterns_insert); tcase_add_test(tcase, test_pcre_patterns_insert);
tcase_add_test(tcase, test_pcre_patterns_insert_2); tcase_add_test(tcase, test_pcre_patterns_insert_2);
tcase_add_test(tcase, test_pcre_patterns_insert_3); tcase_add_test(tcase, test_pcre_patterns_insert_3);
tcase_add_test(tcase, test_feedback);
tcase_set_timeout(tcase, 30); tcase_set_timeout(tcase, 30);
suite_add_tcase(suite, tcase); suite_add_tcase(suite, tcase);