Move the scanned string into the value instead of copying it

The SAX interface documents that the string handed to json_sax::string() may
be moved from, and the DOM handlers already move the one handed to binary().
string() did not, so every string value was copy-constructed out of the
lexer's token buffer, which then kept the buffer alive at its high-water mark
until the next token overwrote it.

Moving hands that buffer to the new value instead. The allocation count is
unchanged - the value needed one either way - but the copy is gone.

  jeopardy      247.3 ms -> 240.9 ms  (-2.6%)
  citm_catalog    4.61 ms ->   4.48 ms (-2.8%)
  40k 30-char strings 7.80 ms -> 7.64 ms (-2.1%)

Note this deliberately does not extend to the object key. Moving the key
hands the lexer's buffer - sized for the largest token seen so far - to a key
that is usually short, so the next value has to grow a fresh buffer. Measured,
that costs 11.9% on a document of many small keys with longer values.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-02 23:34:39 +02:00
parent ec93161a40
commit 2a27755724
2 changed files with 10 additions and 4 deletions
+5 -2
View File
@@ -10739,7 +10739,9 @@ class json_sax_dom_parser
bool string(string_t& val)
{
handle_value(val);
// the interface allows moving the value (see json_sax::string), which
// hands the lexer's buffer to the new value instead of copying it
handle_value(std::move(val));
return true;
}
@@ -11049,7 +11051,8 @@ class json_sax_dom_callback_parser
bool string(string_t& val)
{
handle_value(val);
// see json_sax_dom_parser::string()
handle_value(std::move(val));
return true;
}