Skip to content

Commit 15328a1

Browse files
committed
performance optimization
1 parent ec9dce9 commit 15328a1

File tree

2 files changed

+61
-23
lines changed

2 files changed

+61
-23
lines changed

src/request_body_processor/json_backend_jsoncons.cc

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ class RawJsonTokenCursor {
413413
std::size_t m_offset{0};
414414
};
415415

416-
std::string rawNumberFromContext(const std::string &input,
416+
std::string_view rawNumberFromContext(const std::string &input,
417417
jsoncons::staj_event_type event_type, const jsoncons::ser_context &context,
418418
const jsoncons::staj_event &event, std::string_view scanned_token) {
419419
const std::size_t begin = context.begin_position();
@@ -422,33 +422,27 @@ std::string rawNumberFromContext(const std::string &input,
422422
if (begin < end && end <= input.size()) {
423423
std::string_view candidate(input.data() + begin, end - begin);
424424
if (tokenMatchesNumericEvent(event_type, candidate)) {
425-
return std::string(candidate);
425+
return candidate;
426426
}
427427
}
428428

429429
if (tokenMatchesNumericEvent(event_type, scanned_token)) {
430-
return std::string(scanned_token);
430+
return scanned_token;
431431
}
432432

433433
if (isNumericStringEvent(event)) {
434434
std::error_code error;
435435
jsoncons::string_view decoded = event.get<jsoncons::string_view>(error);
436436
if (error) {
437-
return "";
437+
return std::string_view();
438438
}
439439
if (isValidJsonNumber(std::string_view(decoded.data(), decoded.size()))) {
440-
return std::string(decoded.data(), decoded.size());
440+
return std::string_view(decoded.data(), decoded.size());
441441
}
442-
return "";
442+
return std::string_view();
443443
}
444444

445-
std::error_code error;
446-
std::string fallback = event.get<std::string>(error);
447-
if (error) {
448-
return "";
449-
}
450-
451-
return fallback;
445+
return std::string_view();
452446
}
453447

454448
JsonParseResult emitEvent(const std::string &input, JsonEventSink *sink,
@@ -508,7 +502,7 @@ JsonParseResult emitEvent(const std::string &input, JsonEventSink *sink,
508502
return fromJsonconsError(error, context);
509503
}
510504
if (isNumericStringEvent(event)) {
511-
std::string raw_number = rawNumberFromContext(input,
505+
std::string_view raw_number = rawNumberFromContext(input,
512506
jsoncons::staj_event_type::double_value, context, event,
513507
raw_token);
514508
if (raw_number.empty()) {
@@ -551,7 +545,7 @@ JsonParseResult emitEvent(const std::string &input, JsonEventSink *sink,
551545
case jsoncons::staj_event_type::uint64_value:
552546
case jsoncons::staj_event_type::double_value:
553547
case jsoncons::staj_event_type::half_value: {
554-
std::string raw_number = rawNumberFromContext(input,
548+
std::string_view raw_number = rawNumberFromContext(input,
555549
event.event_type(), context, event, raw_token);
556550
if (raw_number.empty()) {
557551
return makeResult(JsonParseStatus::InternalError,

src/request_body_processor/json_backend_simdjson.cc

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
#include "src/request_body_processor/json_backend.h"
2121

22+
#include <algorithm>
2223
#include <chrono>
2324
#include <cstdint>
25+
#include <memory>
2426
#include <string>
2527
#include <utility>
2628

@@ -87,6 +89,51 @@ JsonParseResult fromSimdjsonError(simdjson::error_code error) {
8789
}
8890
}
8991

92+
simdjson::ondemand::parser &getReusableSimdjsonParser() {
93+
thread_local std::unique_ptr<simdjson::ondemand::parser> parser;
94+
if (parser == nullptr) {
95+
#ifdef MSC_JSON_AUDIT_INSTRUMENTATION
96+
const auto parser_start = std::chrono::steady_clock::now();
97+
parser.reset(new simdjson::ondemand::parser());
98+
recordSimdjsonParserConstruction(static_cast<std::uint64_t>(
99+
std::chrono::duration_cast<std::chrono::nanoseconds>(
100+
std::chrono::steady_clock::now() - parser_start).count()));
101+
#else
102+
parser.reset(new simdjson::ondemand::parser());
103+
#endif
104+
}
105+
return *parser;
106+
}
107+
108+
std::size_t clampRequestedMaxDepth(std::size_t input_size,
109+
const JsonBackendParseOptions &options) {
110+
const std::size_t requested_depth = options.technical_max_depth > 0
111+
? static_cast<std::size_t>(options.technical_max_depth) : 1;
112+
const std::size_t max_possible_depth = (input_size / 2) + 1;
113+
return std::min(requested_depth, std::max<std::size_t>(1,
114+
max_possible_depth));
115+
}
116+
117+
simdjson::error_code prepareParser(simdjson::ondemand::parser *parser,
118+
std::size_t input_size, const JsonBackendParseOptions &options) {
119+
if (parser == nullptr) {
120+
return simdjson::MEMALLOC;
121+
}
122+
123+
const JsonBackendParseOptions default_options;
124+
std::size_t required_max_depth = parser->max_depth();
125+
if (options.technical_max_depth != default_options.technical_max_depth) {
126+
required_max_depth = clampRequestedMaxDepth(input_size, options);
127+
}
128+
129+
if (parser->capacity() >= input_size
130+
&& parser->max_depth() == required_max_depth) {
131+
return simdjson::SUCCESS;
132+
}
133+
134+
return parser->allocate(input_size, required_max_depth);
135+
}
136+
90137
template <typename ResultType, typename TargetType>
91138
JsonParseResult getResult(ResultType &&result, TargetType *target) {
92139
if (auto error = std::forward<ResultType>(result).get(*target); error) {
@@ -361,26 +408,23 @@ class JsonBackendWalker {
361408

362409
JsonParseResult parseDocumentWithSimdjson(const std::string &input,
363410
JsonEventSink *sink, const JsonBackendParseOptions &options) {
364-
(void) options;
365-
366411
if (sink == nullptr) {
367412
return makeResult(JsonParseStatus::InternalError,
368413
JsonSinkStatus::InternalError, "JSON event sink is null.");
369414
}
370415

416+
simdjson::ondemand::parser &parser = getReusableSimdjsonParser();
417+
if (auto error = prepareParser(&parser, input.size(), options); error) {
418+
return fromSimdjsonError(error);
419+
}
420+
371421
#ifdef MSC_JSON_AUDIT_INSTRUMENTATION
372-
const auto parser_start = std::chrono::steady_clock::now();
373-
simdjson::ondemand::parser parser;
374-
recordSimdjsonParserConstruction(static_cast<std::uint64_t>(
375-
std::chrono::duration_cast<std::chrono::nanoseconds>(
376-
std::chrono::steady_clock::now() - parser_start).count()));
377422
const auto padded_start = std::chrono::steady_clock::now();
378423
simdjson::padded_string padded(input);
379424
recordSimdjsonPaddedCopy(input.size(), static_cast<std::uint64_t>(
380425
std::chrono::duration_cast<std::chrono::nanoseconds>(
381426
std::chrono::steady_clock::now() - padded_start).count()));
382427
#else
383-
simdjson::ondemand::parser parser;
384428
simdjson::padded_string padded(input);
385429
#endif
386430
simdjson::ondemand::document document;

0 commit comments

Comments
 (0)