diff options
Diffstat (limited to 'flatcc/test/benchmark/benchflatccjson/benchflatccjson.c')
-rw-r--r-- | flatcc/test/benchmark/benchflatccjson/benchflatccjson.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/flatcc/test/benchmark/benchflatccjson/benchflatccjson.c b/flatcc/test/benchmark/benchflatccjson/benchflatccjson.c new file mode 100644 index 0000000..26ee291 --- /dev/null +++ b/flatcc/test/benchmark/benchflatccjson/benchflatccjson.c @@ -0,0 +1,182 @@ +#define BENCH_TITLE "flatcc json parser and printer for C" + +/* + * NOTE: + * + * Using dtoa_grisu3.c over sprintf("%.17g") more than doubles the + * encoding performance of this benchmark from 3.3 us/op to 1.3 us/op. + */ + +#include <stdlib.h> + +/* + * Builder is only needed so we can create the initial buffer to encode + * json from, but it also includes the reader which is needed calculate + * the decoded checksum after parsing. + */ +#include "flatbench_builder.h" + +#include "flatbench_json_parser.h" +#include "flatbench_json_printer.h" + +#define C(x) FLATBUFFERS_WRAP_NAMESPACE(benchfb_FooBarContainer, x) +#define FooBar(x) FLATBUFFERS_WRAP_NAMESPACE(benchfb_FooBar, x) +#define Bar(x) FLATBUFFERS_WRAP_NAMESPACE(benchfb_Bar, x) +#define Foo(x) FLATBUFFERS_WRAP_NAMESPACE(benchfb_Foo, x) +#define Enum(x) FLATBUFFERS_WRAP_NAMESPACE(benchfb_Enum, x) +#define True flatbuffers_true +#define False flatbuffers_false +#define StringLen flatbuffers_string_len + +typedef struct flatcc_jsonbench { + flatcc_builder_t builder; + flatcc_json_parser_t parser; + flatcc_json_printer_t printer; + + /* Holds the source data to print (encode) from. */ + char bin[1000]; + size_t bin_size; + /* Extra buffer for extracting the parse (decoded) into. */ + char decode_buffer[1000]; + /* + * The target encode / source decode buffer is provided by the + * benchmark framework. + */ +} flatcc_jsonbench_t; + +int flatcc_jsonbench_init(flatcc_jsonbench_t *bench) +{ + int i, veclen = 3; + void *buffer_ok; + flatcc_builder_t *B = &bench->builder; + + flatcc_builder_init(B); + + /* Generate the data needed to print from, just once. */ + C(start_as_root(B)); + C(list_start(B)); + for (i = 0; i < veclen; ++i) { + /* + * By using push_start instead of push_create we can construct + * the sibling field (of Bar type) in-place on the stack, + * otherwise we would need to create a temporary Bar struct. + */ + C(list_push_start(B)); + FooBar(sibling_create(B, + 0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i, + 123456 + i, 3.14159f + i, 10000 + i)); + FooBar(name_create_str(B, "Hello, World!")); + FooBar(rating_add(B, 3.1415432432445543543 + i)); + FooBar(postfix_add(B, '!' + i)); + C(list_push_end(B)); + } + C(list_end(B)); + C(location_create_str(B, "https://www.example.com/myurl/")); + C(fruit_add(B, Enum(Bananas))); + C(initialized_add(B, True)); + C(end_as_root(B)); + + buffer_ok = flatcc_builder_copy_buffer(B, bench->bin, sizeof(bench->bin)); + bench->bin_size = flatcc_builder_get_buffer_size(B); + + flatcc_builder_reset(&bench->builder); + return !buffer_ok; +} + +void flatcc_jsonbench_clear(flatcc_jsonbench_t *bench) +{ + flatcc_json_printer_clear(&bench->printer); + flatcc_builder_clear(&bench->builder); + // parser does not need to be cleared. +} + +/* + * For a buffer large enough to hold encoded representation. + * + * 1000 is enough for compact json, but for pretty printing we must up. + */ +#define BENCHMARK_BUFSIZ 10000 + +/* Interface to main benchmark logic. */ +#define DECLARE_BENCHMARK(BM) \ + flatcc_jsonbench_t flatcc_jsonbench, *BM; \ + BM = &flatcc_jsonbench; \ + flatcc_jsonbench_init(BM); + +#define CLEAR_BENCHMARK(BM) flatcc_jsonbench_clear(BM); + +int encode(flatcc_jsonbench_t *bench, void *buffer, size_t *size) +{ + int ret; + + flatcc_json_printer_init_buffer(&bench->printer, buffer, *size); + /* + * Normally avoid setting indentation - this yields compact + * spaceless json which is what you want in resource critical + * parsing and printing. But - it doesn't get that much slower, + * so interesting to benchmark. Improve by enabling SSE4_2, but + * generally not worth the trouble. + */ + //flatcc_json_printer_set_indent(&bench->printer, 8); + + /* + * Unquoted makes it slightly slower, noenum hardly makes a + * difference - for this particular data set. + */ + // flatcc_json_printer_set_noenum(&bench->printer, 1); + // flatcc_json_printer_set_unquoted(&bench->printer, 1); + ret = flatbench_print_json(&bench->printer, bench->bin, bench->bin_size); + *size = flatcc_json_printer_flush(&bench->printer); + + return ret < 0 ? ret : 0; +} + +int64_t decode(flatcc_jsonbench_t *bench, void *buffer, size_t size, int64_t sum) +{ + unsigned int i; + int ret; + flatcc_builder_t *B = &bench->builder; + + C(table_t) foobarcontainer; + FooBar(vec_t) list; + FooBar(table_t) foobar; + Bar(struct_t) bar; + Foo(struct_t) foo; + + flatcc_builder_reset(B); + ret = flatbench_parse_json(B, &bench->parser, buffer, size, 0); + if (ret) { + return 0; + } + if (!flatcc_builder_copy_buffer(B, + bench->decode_buffer, sizeof(bench->decode_buffer))) { + return 0; + } + + /* Traverse parsed result to calculate checksum. */ + + foobarcontainer = C(as_root(bench->decode_buffer)); + sum += C(initialized(foobarcontainer)); + sum += StringLen(C(location(foobarcontainer))); + sum += C(fruit(foobarcontainer)); + list = C(list(foobarcontainer)); + for (i = 0; i < FooBar(vec_len(list)); ++i) { + foobar = FooBar(vec_at(list, i)); + sum += StringLen(FooBar(name(foobar))); + sum += FooBar(postfix(foobar)); + sum += (int64_t)FooBar(rating(foobar)); + bar = FooBar(sibling(foobar)); + sum += (int64_t)Bar(ratio(bar)); + sum += Bar(size(bar)); + sum += Bar(time(bar)); + foo = Bar(parent(bar)); + sum += Foo(count(foo)); + sum += Foo(id(foo)); + sum += Foo(length(foo)); + sum += Foo(prefix(foo)); + } + return sum + 2 * sum; +} + +/* Copy to same folder before compilation or use include directive. */ +#include "benchmain.h" |