Write strings and keys of up to 32 characters in one go with vectors

The previous change handles plain strings of up to 16 characters with
two overlapping 8-byte words. With SSE2 or NEON, two overlapping 16-byte
vectors do the same for 16 to 32 characters: one test for a quote,
backslash, control character, DEL or non-ASCII byte over both, and two
stores. Targets without either keep the limit of 16.

Apple M1, Apple clang, retired instructions per dump(), on top of the
previous changes (it replaces the table of #5878 for these strings):
  keys and values of 1..40 characters 7.07M -> 4.94M (-30 %)
  twitter 4.15M -> 3.30M (-21 %)   paths 9.09M -> 8.08M (-11 %)
  citm_catalog 5.76M -> 5.53M (-4 %)   jeopardy 461M -> 451M (-2 %)
Linux x86-64 (callgrind), gcc 13 / clang 18: twitter -11 % / -9 %,
keys and values of 1..40 characters -19 % / -17 %, paths -7 % / -7 %.
Documents without strings in that range are unchanged.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-22 09:28:23 +02:00
1 parent 731363a325
commit ae30ba55c3
3 files changed
+145 -30

No files matched your search

+5 -4
View File
@@ -1583,9 +1583,10 @@ TEST_CASE("invalid UTF-8 at every position is handled like the reference")
TEST_CASE("short strings are written like the reference, as values and as keys")
{
// strings of up to 16 characters that need no escaping are written as a
// whole (together with the quotes and, for a key, the colon); everything
// else, including a string that is merely short, takes the general path.
// strings of up to 16 characters (32 with vector instructions) that need no
// escaping are written as a whole (together with the quotes and, for a key,
// the colon); everything else, including a string that is merely short,
// takes the general path.
// Every length around the edges of the size classes of the fast path is
// combined with each kind of byte that must send a string to the general
// path, at each position, and compared with the reference for values and,
@@ -1595,7 +1596,7 @@ TEST_CASE("short strings are written like the reference, as values and as keys")
"\"", "\\", "\n", "\x1f", "\x7f", "\xc3\xa9", "\xe2\x82\xac", "\xf0\x9f\x98\x80", "\xff", "\x80", "\xc3"
};
for (std::size_t length = 0; length <= 20; ++length)
for (std::size_t length = 0; length <= 36; ++length)
{
const std::string plain(length, 'k');
check_dump_against_reference(plain, false);