From 15161669ec01f916c3428d6a93d028bb51a47e42 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Wed, 12 Dec 2018 10:19:32 -0500 Subject: [PATCH] Added a version of RapidJSON with static alloc. --- benchmark/parsingcompetition.cpp | 146 +++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 47 deletions(-) diff --git a/benchmark/parsingcompetition.cpp b/benchmark/parsingcompetition.cpp index 200d5745..7f8e01e7 100644 --- a/benchmark/parsingcompetition.cpp +++ b/benchmark/parsingcompetition.cpp @@ -1,74 +1,73 @@ -#include #include "simdjson/jsonparser.h" +#include #include "benchmark.h" // #define RAPIDJSON_SSE2 // bad for performance // #define RAPIDJSON_SSE42 // bad for performance #include "rapidjson/document.h" -#include "rapidjson/reader.h" +#include "rapidjson/reader.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" -#include "json11.cpp" -#include "sajson.h" #include "fastjson.cpp" #include "fastjson_dom.cpp" #include "gason.cpp" -extern "C" -{ -#include "ultrajsondec.c" +#include "json11.cpp" +#include "sajson.h" +extern "C" { #include "ujdecode.h" +#include "ultrajsondec.c" } using namespace rapidjson; using namespace std; - // fastjson has a tricky interface -void on_json_error( void *, const fastjson::ErrorContext& ec) { - //std::cerr<<"ERROR: "<= argc) { cerr << "Usage: " << argv[0] << " \n"; cerr << "Or " << argv[0] << " -v \n"; - cerr << "To enable parsers that are not standard compliant, use the -a flag\n"; + cerr << "To enable parsers that are not standard compliant, use the -a " + "flag\n"; exit(1); } - const char * filename = argv[optind]; - if(optind + 1 < argc) { - cerr << "warning: ignoring everything after " << argv[optind + 1] << endl; + const char *filename = argv[optind]; + if (optind + 1 < argc) { + cerr << "warning: ignoring everything after " << argv[optind + 1] << endl; } std::string_view p; try { p = get_corpus(filename); - } catch (const std::exception& e) { // caught by reference to base + } catch (const std::exception &e) { // caught by reference to base std::cout << "Could not load the file " << filename << std::endl; return EXIT_FAILURE; } - + if (verbose) { std::cout << "Input has "; if (p.size() > 1024 * 1024) @@ -88,42 +87,95 @@ int main(int argc, char *argv[]) { } int repeat = 10; int volume = p.size(); - BEST_TIME("simdjson (dynamic mem) ", build_parsed_json(p).isValid(), true, , repeat, volume, true); + BEST_TIME("simdjson (dynamic mem) ", build_parsed_json(p).isValid(), true, , + repeat, volume, true); - BEST_TIME("simdjson (static alloc) ", json_parse(p, pj), true, , repeat, volume, true); + BEST_TIME("simdjson (static alloc) ", json_parse(p, pj), true, , repeat, + volume, true); rapidjson::Document d; char *buffer = (char *)malloc(p.size() + 1); memcpy(buffer, p.data(), p.size()); buffer[p.size()] = '\0'; - // - // Todo: It is possible to preallocate a block of memory with RapidJSON using a MemoryAllocator. - BEST_TIME("RapidJSON", + + BEST_TIME( + "RapidJSON", d.Parse((const char *)buffer).HasParseError(), false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); - BEST_TIME("RapidJSON (insitu)", d.ParseInsitu(buffer).HasParseError(), false, - memcpy(buffer, p.data(), p.size()), repeat, volume, true); + BEST_TIME("RapidJSON (insitu)", + d.ParseInsitu(buffer).HasParseError(), + false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + typedef rapidjson::GenericDocument, rapidjson::MemoryPoolAllocator<>, + rapidjson::MemoryPoolAllocator<>> + RapidDocumentType; + size_t rapidvaallocsize = p.size() * 128; // allocate plenty of memory + size_t rapidallocsize = p.size() * 4096; // allocate plenty of memory + char *rapidvalueBuffer = (char *)malloc(rapidvaallocsize); + char *rapidparseBuffer = (char *)malloc(rapidallocsize); + if ((rapidvalueBuffer != NULL) && (rapidvalueBuffer != NULL)) { + rapidjson::MemoryPoolAllocator<> valueAllocator(rapidvalueBuffer, + rapidvaallocsize); + rapidjson::MemoryPoolAllocator<> parseAllocator(rapidparseBuffer, + rapidallocsize); + RapidDocumentType preallocedd(&valueAllocator, rapidvaallocsize, + &parseAllocator); - BEST_TIME("sajson (dynamic mem, insitu)", sajson::parse(sajson::dynamic_allocation(), sajson::mutable_string_view(p.size(), buffer)).is_valid(), true, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + BEST_TIME( + "RapidJSON (static alloc)", + preallocedd.Parse((const char *)buffer) + .HasParseError(), + false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + BEST_TIME("RapidJSON (static alloc, insitu)", + preallocedd.ParseInsitu(buffer) + .HasParseError(), + false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + assert(valueAllocator.Size() <= rapidvaallocsize); + assert(parseAllocator.Size() <= rapidallocsize); + } + free(rapidvalueBuffer); + free(rapidparseBuffer); + + BEST_TIME("sajson (dynamic mem, insitu)", + sajson::parse(sajson::dynamic_allocation(), + sajson::mutable_string_view(p.size(), buffer)) + .is_valid(), + true, memcpy(buffer, p.data(), p.size()), repeat, volume, true); size_t astbuffersize = p.size(); - size_t * ast_buffer = (size_t *) malloc(astbuffersize * sizeof(size_t)); + size_t *ast_buffer = (size_t *)malloc(astbuffersize * sizeof(size_t)); - BEST_TIME("sajson (static alloc, insitu)", sajson::parse(sajson::bounded_allocation(ast_buffer, astbuffersize), sajson::mutable_string_view(p.size(), buffer)).is_valid(), true, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + BEST_TIME("sajson (static alloc, insitu)", + sajson::parse(sajson::bounded_allocation(ast_buffer, astbuffersize), + sajson::mutable_string_view(p.size(), buffer)) + .is_valid(), + true, memcpy(buffer, p.data(), p.size()), repeat, volume, true); std::string json11err; - if(all) BEST_TIME("dropbox (json11) ", (( json11::Json::parse(buffer,json11err).is_null() ) || ( ! json11err.empty() )), false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + if (all) + BEST_TIME("dropbox (json11) ", + ((json11::Json::parse(buffer, json11err).is_null()) || + (!json11err.empty())), + false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); - if(all) BEST_TIME("fastjson ", fastjson_parse(buffer), true, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + if (all) + BEST_TIME("fastjson ", fastjson_parse(buffer), true, + memcpy(buffer, p.data(), p.size()), repeat, volume, true); JsonValue value; JsonAllocator allocator; char *endptr; - if(all) BEST_TIME("gason ", jsonParse(buffer, &endptr, &value, allocator), JSON_OK, memcpy(buffer, p.data(), p.size()), repeat, volume, true); + if (all) + BEST_TIME("gason ", + jsonParse(buffer, &endptr, &value, allocator), JSON_OK, + memcpy(buffer, p.data(), p.size()), repeat, volume, true); void *state; - if(all) BEST_TIME("ultrajson ", (UJDecode(buffer, p.size(), NULL, &state) == NULL), false, memcpy(buffer, p.data(), p.size()), repeat, volume, true); - BEST_TIME("memcpy ", (memcpy(buffer, p.data(), p.size()) == buffer), true, , repeat, volume, true); - free((void*)p.data()); + if (all) + BEST_TIME("ultrajson ", + (UJDecode(buffer, p.size(), NULL, &state) == NULL), false, + memcpy(buffer, p.data(), p.size()), repeat, volume, true); + BEST_TIME("memcpy ", + (memcpy(buffer, p.data(), p.size()) == buffer), true, , repeat, + volume, true); + free((void *)p.data()); free(ast_buffer); free(buffer); } -