From 6e68b6a17d33e79b4274550e70580cfdcdbbb914 Mon Sep 17 00:00:00 2001 From: Gabor Adam Toth Date: Tue, 17 May 2011 00:27:26 +0200 Subject: [PATCH] bench: added test tools, updated results; added inline option for parse & render --- .gitignore | 5 +- bench/.gitignore | 3 ++ bench/results.org | 20 ++++---- include/psyc/parse.h | 6 +++ include/psyc/render.h | 6 +++ src/parse.c | 6 +++ src/render.c | 6 +++ test/Makefile | 13 +++-- test/test.h | 28 +++++++++++ test/testJson.c | 113 ++++++++++++++++++++++++++++++++++++++++++ test/testJsonGlib.c | 100 +++++++++++++++++++++++++++++++++++++ test/testPsyc.c | 38 ++++---------- test/testPsycFast.c | 88 -------------------------------- test/testPsycSpeed.c | 74 +++++++++++++++++++++++++++ test/testStrlen.c | 63 +++++++++++++++++++++++ 15 files changed, 438 insertions(+), 131 deletions(-) create mode 100644 bench/.gitignore create mode 100644 test/testJson.c create mode 100644 test/testJsonGlib.c delete mode 100644 test/testPsycFast.c create mode 100644 test/testPsycSpeed.c create mode 100644 test/testStrlen.c diff --git a/.gitignore b/.gitignore index 754a28f..b6b2544 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,10 @@ test/testMatch test/testParser test/testRender test/testPsyc -test/testPsycFast +test/testPsycSpeed +test/testJson +test/testJsonGlib +test/testStrlen test/testText test/isRoutingVar test/getVarType diff --git a/bench/.gitignore b/bench/.gitignore new file mode 100644 index 0000000..f93db6e --- /dev/null +++ b/bench/.gitignore @@ -0,0 +1,3 @@ +*.html +*.pdf +packets/ diff --git a/bench/results.org b/bench/results.org index e46d1f6..48dc2f1 100644 --- a/bench/results.org +++ b/bench/results.org @@ -5,23 +5,21 @@ Parsing time of 1 000 000 packets in milliseconds: -| | libpsyc | libpsyc fast | json-c | json-glib | libxml sax | libxml | rapidxml fast | rapidxml | -|-----------+---------+--------------+--------+-----------+------------+--------+---------------+----------| -| presence | 597 | 246 | 3247 | 10197 | 4997 | 7557 | 1643 | 1719 | -| chat msg | 714 | 320 | | | 5997 | 9777 | 1799 | 1893 | -| activity | 903 | 366 | 5768 | 16846 | 13357 | 28858 | 4001 | 4419 | -| user prof | 1806 | 608 | 5847 | 17468 | 7350 | 12377 | 2218 | 2477 | -|-----------+---------+--------------+--------+-----------+------------+--------+---------------+----------| -| / | < | > | < | > | < | > | < | > | +| | strlen | libpsyc | json-c | json-glib | libxml sax | libxml | rapidxml | +|-----------+--------+---------+--------+-----------+------------+--------+----------| +| presence | 30 | 246 | 2463 | 10197 | 4997 | 7557 | 1719 | +| chat msg | 41 | 320 | | | 5997 | 9777 | 1893 | +| activity | 42 | 366 | 4666 | 16846 | 13357 | 28858 | 4419 | +| user prof | 55 | 608 | 4715 | 17468 | 7350 | 12377 | 2477 | +|-----------+--------+---------+--------+-----------+------------+--------+----------| +| / | < | < | < | > | < | > | > | * Commands used -: ./testPsyc -snc 1000000 -f $file -: ./testPsycFast -sc 1000000 -f $file +: ./testPsycSpeed -sc 1000000 -f $file : ./testJson -snc 1000000 -f $file : ./testJsonGlib -snc 1000000 -f $file : ./testStrlen -sc 1000000 -f $file : ./rapidxml 1000000 $file -: fast_mode=1 ./rapidxml 1000000 $file : ./libxml 1000000 $file : ./libxml-sax 1000000 $file diff --git a/include/psyc/parse.h b/include/psyc/parse.h index 4c5c28d..0f2332c 100644 --- a/include/psyc/parse.h +++ b/include/psyc/parse.h @@ -428,6 +428,9 @@ const char * psyc_getParseRemainingBuffer (psycParseState *state) * @param value In case of a modifier it will point to the value, * in case of the body it will point to the data. */ +#ifdef __INLINE_PSYC_PARSE +static inline +#endif psycParseRC psyc_parse (psycParseState *state, char *oper, psycString *name, psycString *value); @@ -443,6 +446,9 @@ psycParseRC psyc_parse (psycParseState *state, char *oper, * @param value Contains the list to be parsed. * @param elem It will point to the next element in the list. */ +#ifdef __INLINE_PSYC_PARSE +static inline +#endif psycParseListRC psyc_parseList (psycParseListState *state, psycString *elem); /** @} */ // end of parse group diff --git a/include/psyc/render.h b/include/psyc/render.h index 12fd42d..2f13793 100644 --- a/include/psyc/render.h +++ b/include/psyc/render.h @@ -58,11 +58,17 @@ typedef enum * @see psyc_newRawPacket2 * @see psyc_setPacketLength */ +#ifdef __INLINE_PSYC_RENDER +static inline +#endif psycRenderRC psyc_render (psycPacket *packet, char *buffer, size_t buflen); /** * Render a PSYC list into a buffer. */ +#ifdef __INLINE_PSYC_RENDER +static inline +#endif psycRenderListRC psyc_renderList (psycList *list, char *buffer, size_t buflen); /** @} */ // end of render group diff --git a/src/parse.c b/src/parse.c index a1f5798..4248c7c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -202,6 +202,9 @@ parseRC psyc_parseModifier (psycParseState *state, char *oper, } /** Parse PSYC packets. */ +#ifdef __INLINE_PSYC_PARSE +static inline +#endif psycParseRC psyc_parse (psycParseState *state, char *oper, psycString *name, psycString *value) { @@ -483,6 +486,9 @@ psycParseRC psyc_parse (psycParseState *state, char *oper, } /** List parser. */ +#ifdef __INLINE_PSYC_PARSE +static inline +#endif psycParseListRC psyc_parseList (psycParseListState *state, psycString *elem) { if (state->cursor >= state->buffer.length) diff --git a/src/render.c b/src/render.c index ad4822d..449d280 100644 --- a/src/render.c +++ b/src/render.c @@ -2,6 +2,9 @@ #include #include +#ifdef __INLINE_PSYC_RENDER +static inline +#endif psycRenderListRC psyc_renderList (psycList *list, char *buffer, size_t buflen) { size_t i, cur = 0; @@ -64,6 +67,9 @@ size_t psyc_renderModifier (psycModifier *mod, char *buffer) return cur; } +#ifdef __INLINE_PSYC_RENDER +static inline +#endif psycRenderRC psyc_render (psycPacket *packet, char *buffer, size_t buflen) { size_t i, cur = 0, len; diff --git a/test/Makefile b/test/Makefile index 4d3c38e..934ed1c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ CFLAGS_COMMON = -Wall -std=c99 ${OPT} CFLAGS = -I../include -I../src ${CFLAGS_COMMON} LDFLAGS = -L../lib LOADLIBES = -lpsyc -lm -TARGETS = testPsyc testPsycFast testParser testMatch testRender testText isRoutingVar getVarType +TARGETS = testPsyc testPsycSpeed testParser testMatch testRender testText isRoutingVar getVarType O = test.o WRAPPER = DIET = diet @@ -21,8 +21,15 @@ all: ${TARGETS} it: all testPsyc: LOADLIBES := ${LOADLIBES} ${LOADLIBES_NET} -testPsycFast: LOADLIBES := ${LOADLIBES} ${LOADLIBES_NET} -#testPsycFast: LOADLIBES := ${LOADLIBES_NET} +testPsycSpeed: LOADLIBES := ${LOADLIBES} ${LOADLIBES_NET} +#testPsycSpeed: LOADLIBES := ${LOADLIBES_NET} + +testJson: LOADLIBES := ${LOADLIBES_NET} -ljson + +testJsonGlib: CFLAGS = ${CFLAGS_COMMON} -I/usr/include/json-glib-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include +testJsonGlib: LOADLIBES := ${LOADLIBES_NET} -ljson-glib-1.0 + +testStrlen: LOADLIBES := ${LOADLIBES_NET} diet: WRAPPER = ${DIET} diet: all diff --git a/test/test.h b/test/test.h index 8b7b0be..ee0d1f5 100644 --- a/test/test.h +++ b/test/test.h @@ -14,6 +14,34 @@ # define NUM_PARSERS 100 #endif +#define CASE_f case 'f': filename = optarg; break; +#define CASE_p case 'p': port = optarg; check_range(c, optarg, 1, 0); break; +#define CASE_b case 'b': recv_buf_size = atoi(optarg); check_range(c, optarg, 1, RECV_BUF_SIZE); break; +#define CASE_c case 'c': count = atoi(optarg); check_range(c, optarg, 1, 0); break; +#define CASE_n case 'n': no_render = 1; break; +#define CASE_m case 'm': multiple = 1; break; +#define CASE_q case 'q': quiet = 1; break; +#define CASE_r case 'r': routing_only = 1; break; +#define CASE_s case 's': stats = 1; break; +#define CASE_v case 'v': verbose++; break; +#define CASE_P case 'P': progress = 1; break; +#define CASE_S case 'S': single = 1; break; +#define HELP_FILE(name, opts) name " -f [-b ] [-c ] [-" opts "]\n" +#define HELP_PORT(name, opts) name " [-p ] [-b ] [-" opts "]\n" +#define HELP_f " -f \tInput file name\n" +#define HELP_p " -p \t\tListen on TCP port, default is %s\n" +#define HELP_b " -b \tRead/receive buffer size, default is %d\n" +#define HELP_c " -c \t\tParse data from file times\n" +#define HELP_m " -m\t\t\tParse multiple packets from file\n" +#define HELP_n " -n\t\t\tNo rendering, only parsing\n" +#define HELP_q " -q\t\t\tQuiet mode, don't output rendered string\n" +#define HELP_r " -r\t\t\tParse routing header only\n" +#define HELP_S " -S\t\t\tSingle packet mode, close connection after parsing one packet\n" +#define HELP_s " -s\t\t\tShow statistics at the end\n" +#define HELP_v " -v\t\t\tVerbose, can be specified multiple times for more verbosity\n" +#define HELP_P " -P\t\t\tShow progress\n" +#define HELP_h " -h\t\t\tShow this help\n" + void test_init(int i); int test_input(int i, char *recvbuf, size_t nbytes); diff --git a/test/testJson.c b/test/testJson.c new file mode 100644 index 0000000..d1c7e21 --- /dev/null +++ b/test/testJson.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "test.c" + +// cmd line args +char *filename, *port = "4441"; +uint8_t verbose, stats; +uint8_t multiple, single, no_render, quiet, progress; +size_t count = 1, recv_buf_size = RECV_BUF_SIZE; + +int exit_code; + +json_object *obj; +json_tokener *tok; +enum json_tokener_error error; + +int main (int argc, char **argv) { + int c; + + while ((c = getopt (argc, argv, "f:p:b:c:mnqsvPSh")) != -1) { + switch (c) { + CASE_f CASE_p CASE_b CASE_c + CASE_m CASE_n CASE_q CASE_s + CASE_v CASE_S CASE_P + case 'h': + printf( + HELP_FILE("testJson", "mnqSsvP") + HELP_PORT("testJson", "nqsvP") + HELP_f HELP_p HELP_b HELP_c + HELP_m HELP_n HELP_q HELP_S + HELP_s HELP_v HELP_P HELP_h, + port, RECV_BUF_SIZE); + exit(0); + case '?': exit(-1); + default: abort(); + } + } + + if (filename) + test_file(filename, count, recv_buf_size); + else + test_server(port, count, recv_buf_size); + + return exit_code; +} + +void test_init (int i) { + tok = json_tokener_new(); +} + +int test_input (int i, char *recvbuf, size_t nbytes) { + size_t cursor = 0; + int r, ret = 0; + + json_tokener_reset(tok); + + do { + obj = json_tokener_parse_ex(tok, recvbuf + cursor, nbytes - cursor); + cursor += tok->char_offset; + + if (verbose) + printf("#%d\n", tok->err); + + switch (tok->err) { + case json_tokener_continue: + return 0; + + case json_tokener_success: + if (!no_render) { + const char *str = json_object_to_json_string(obj); + if (!quiet) { + size_t len = strlen(str); + if (filename) { + r = write(1, str, len); + r = write(1, "\n", 1); + } else { + send(i, str, len, 0); + send(i, "\n", 1, 0); + } + } + } + + json_object_put(obj); + + if (verbose) + printf("# Done parsing.\n"); + else if (progress) + r = write(1, ".", 1); + if ((filename && !multiple) || (!filename && single)) + return -1; + break; + + default: + printf("parse error\n"); + exit_code = tok->err; + return -1; + } + } while (cursor < nbytes); + + return ret; +} diff --git a/test/testJsonGlib.c b/test/testJsonGlib.c new file mode 100644 index 0000000..94e9373 --- /dev/null +++ b/test/testJsonGlib.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "test.c" + +// cmd line args +char *filename, *port = "4442"; +uint8_t verbose, stats; +uint8_t no_render, quiet, progress; +size_t count = 1, recv_buf_size = RECV_BUF_SIZE; + +int exit_code; + +JsonParser *parser; +JsonGenerator *generator; + +int main (int argc, char **argv) { + int c; + + while ((c = getopt (argc, argv, "f:p:b:c:nqsvPh")) != -1) { + switch (c) { + CASE_f CASE_p CASE_b + CASE_c CASE_n CASE_q + CASE_s CASE_v CASE_P + case 'h': + printf( + HELP_FILE("testJsonGlib", "mnqSsvP") + HELP_PORT("testJsonGlib", "nqsvP") + HELP_f HELP_p HELP_b HELP_c + HELP_m HELP_n HELP_q HELP_S + HELP_s HELP_v HELP_P HELP_h, + port, RECV_BUF_SIZE); + exit(0); + case '?': exit(-1); + default: abort(); + } + } + + if (filename) + test_file(filename, count, recv_buf_size); + else + test_server(port, count, recv_buf_size); + + return exit_code; +} + +void test_init (int i) { + g_type_init(); + parser = json_parser_new(); + generator = json_generator_new(); +} + +int test_input (int i, char *recvbuf, size_t nbytes) { + JsonNode *root; + GError *error; + char *str; + size_t len; + int r, ret; + + ret = json_parser_load_from_data(parser, recvbuf, nbytes, &error); + + if (!ret) { + printf("Parse error\n"); + exit_code = 1; + return -1; + } + + root = json_parser_get_root(parser); + + if (!no_render) { + json_generator_set_root(generator, root); + str = json_generator_to_data(generator, &len);; + if (!quiet) { + if (filename) { + r = write(1, str, len); + r = write(1, "\n", 1); + } else { + send(i, str, len, 0); + send(i, "\n", 1, 0); + } + } + } + + if (verbose) + printf("# Done parsing.\n"); + else if (progress) + r = write(1, ".", 1); + + return ret; +} diff --git a/test/testPsyc.c b/test/testPsyc.c index f3cbf0f..6b4add0 100644 --- a/test/testPsyc.c +++ b/test/testPsyc.c @@ -313,37 +313,19 @@ inline void resetString (psycString *s, uint8_t freeptr) int main (int argc, char **argv) { int c; - while ((c = getopt (argc, argv, "f:p:b:c:nmqrsvPSh")) != -1) { + while ((c = getopt (argc, argv, "f:p:b:c:mnqrsvPSh")) != -1) { switch (c) { - case 'f': filename = optarg; break; - case 'p': port = optarg; check_range(c, optarg, 1, 0); break; - case 'b': recv_buf_size = atoi(optarg); check_range(c, optarg, 1, RECV_BUF_SIZE); break; - case 'c': count = atoi(optarg); check_range(c, optarg, 1, 0); break; - case 'n': no_render = 1; break; - case 'm': multiple = 1; break; - case 'q': quiet = 1; break; - case 'r': routing_only = 1; break; - case 's': stats = 1; break; - case 'v': verbose++; break; - case 'P': progress = 1; break; - case 'S': single = 1; break; + CASE_f CASE_p CASE_b CASE_c + CASE_m CASE_n CASE_q CASE_r + CASE_s CASE_v CASE_S CASE_P case 'h': printf( - "testPsyc -f [-b ] [-c ] [-mnqrSsvP]\n" - "testPsyc [-p ] [-b ] [-nqrsvP]\n" - " -f \tInput file name\n" - " -p \t\tListen on TCP port, default is %s\n" - " -b \tRead/receive buffer size, default is %d\n" - " -c \t\tParse data from file times\n" - " -m\t\t\tParse multiple packets from file\n" - " -n\t\t\tNo rendering, only parsing\n" - " -r\t\t\tParse routing header only\n" - " -q\t\t\tQuiet mode, don't output rendered string\n" - " -S\t\t\tSingle packet mode, close connection after parsing one packet\n" - " -s\t\t\tShow statistics at the end\n" - " -v\t\t\tVerbose, can be specified multiple times for more verbosity\n" - " -P\t\t\tShow progress\n" - " -h\t\t\tShow this help\n", + HELP_FILE("testPsyc", "mnqrSsvP") + HELP_PORT("testPsyc", "nqrsvP") + HELP_f HELP_p HELP_b HELP_c + HELP_m HELP_n HELP_r + HELP_q HELP_S HELP_s + HELP_v HELP_P HELP_h, port, RECV_BUF_SIZE); exit(0); case '?': exit(-1); diff --git a/test/testPsycFast.c b/test/testPsycFast.c deleted file mode 100644 index 0e1aa28..0000000 --- a/test/testPsycFast.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -//#define PSYC_PARSE_INLINE -//#include "../src/parse.c" -#include - -#include "test.c" - -// max size for routing & entity header -#define ROUTING_LINES 16 -#define ENTITY_LINES 32 - -// cmd line args -char *filename, *port = "4440"; -uint8_t verbose, stats; -uint8_t routing_only; -size_t count = 1, recv_buf_size = RECV_BUF_SIZE; - -psycParseState parser; - -void test_init (int i) { - // reset parser state - if (routing_only) - psyc_initParseState2(&parser, PSYC_PARSE_ROUTING_ONLY); - else - psyc_initParseState(&parser); -} - -int test_input (int i, char *recvbuf, size_t nbytes) { - char oper; - psycString name, value; - int ret; - - parser.buffer = (psycString){nbytes, recvbuf}; - parser.cursor = 0; - - for (;;) { - ret = psyc_parse(&parser, &oper, &name, &value); - - if (ret == PSYC_PARSE_COMPLETE || ret < 0) - return -1; - } -} - -int main (int argc, char **argv) { - int c; - while ((c = getopt (argc, argv, "f:p:b:c:qrsvh")) != -1) { - switch (c) { - case 'f': filename = optarg; break; - case 'p': port = optarg; check_range(c, optarg, 1, 0); break; - case 'b': recv_buf_size = atoi(optarg); check_range(c, optarg, 1, RECV_BUF_SIZE); break; - case 'c': count = atoi(optarg); check_range(c, optarg, 1, 0); break; - case 'r': routing_only = 1; break; - case 's': stats = 1; break; - case 'v': verbose++; break; - case 'h': - printf( - "testPsyc -f [-b ] [-c ] [-mnqrSsvP]\n" - "testPsyc [-p ] [-b ] [-nqrsvP]\n" - " -f \tInput file name\n" - " -p \t\tListen on TCP port, default is %s\n" - " -b \tRead/receive buffer size, default is %d\n" - " -c \t\tParse data from file times\n" - " -r\t\t\tParse routing header only\n" - " -s\t\t\tShow statistics at the end\n" - " -h\t\t\tShow this help\n" - " -v\t\t\tVerbose\n", - port, RECV_BUF_SIZE); - exit(0); - case '?': exit(-1); - default: abort(); - } - } - - if (filename) - test_file(filename, count, recv_buf_size); - else - test_server(port, count, recv_buf_size); - - return 0; -} diff --git a/test/testPsycSpeed.c b/test/testPsycSpeed.c new file mode 100644 index 0000000..7baecb5 --- /dev/null +++ b/test/testPsycSpeed.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define __INLINE_PSYC_PARSE +#include "../src/parse.c" +//#include + +#include "test.c" + +// max size for routing & entity header +#define ROUTING_LINES 16 +#define ENTITY_LINES 32 + +// cmd line args +char *filename, *port = "4440"; +uint8_t verbose, stats; +uint8_t routing_only; +size_t count = 1, recv_buf_size = RECV_BUF_SIZE; + +psycParseState parser; + +void test_init (int i) { + if (routing_only) + psyc_initParseState2(&parser, PSYC_PARSE_ROUTING_ONLY); + else + psyc_initParseState(&parser); +} + +int test_input (int i, char *recvbuf, size_t nbytes) { + char oper; + psycString name, value; + int ret; + + psyc_setParseBuffer2(&parser, recvbuf, nbytes); + + for (;;) { + ret = psyc_parse(&parser, &oper, &name, &value); + if (ret == PSYC_PARSE_COMPLETE || ret < 0) + return -1; + } +} + +int main (int argc, char **argv) { + int c; + while ((c = getopt (argc, argv, "f:p:b:c:rsh")) != -1) { + switch (c) { + CASE_f CASE_p CASE_b CASE_c + CASE_r CASE_s + case 'h': + printf( + HELP_FILE("testPsycSpeed", "rs") + HELP_PORT("testPsycSpeed", "rs") + HELP_f HELP_p HELP_b HELP_c + HELP_r HELP_s HELP_h, + port, RECV_BUF_SIZE); + exit(0); + case '?': exit(-1); + default: abort(); + } + } + + if (filename) + test_file(filename, count, recv_buf_size); + else + test_server(port, count, recv_buf_size); + + return 0; +} diff --git a/test/testStrlen.c b/test/testStrlen.c new file mode 100644 index 0000000..6b5785e --- /dev/null +++ b/test/testStrlen.c @@ -0,0 +1,63 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test.c" + +// cmd line args +char *filename, *port = "4443"; +uint8_t verbose, stats; +uint8_t no_render, quiet, progress; +size_t count = 1, recv_buf_size = RECV_BUF_SIZE; + +int exit_code; + +void test_init (int i) { +} + +int test_input (int i, char *recvbuf, size_t nbytes) { + size_t len = strnlen(recvbuf, nbytes); + + if (!len) { + printf("Empty string\n"); + return -1; + } + + return 0; +} + +int main (int argc, char **argv) { + int c; + + while ((c = getopt (argc, argv, "f:p:b:c:sh")) != -1) { + switch (c) { + CASE_f CASE_p CASE_b CASE_c + CASE_s + case 'h': + printf( + HELP_FILE("testStrlen", "s") + HELP_PORT("testStrlen", "s") + HELP_f HELP_p HELP_b HELP_c + HELP_s HELP_h, + port, RECV_BUF_SIZE); + exit(0); + case '?': exit(-1); + default: abort(); + } + } + + if (filename) + test_file(filename, count, recv_buf_size); + else + test_server(port, count, recv_buf_size); + + return exit_code; +}