Write the usual indentation with four stores instead of memset

Every line of a pretty-printed document starts with its indentation, which
was written by calling memset with a length known only at run time.

An indentation of up to 32 characters, with room in the write buffer,
stores four words of the indentation character and claims the part it
needs. Wider indentations and a nearly full buffer take the unchanged
path.

Apple M1, Apple clang, retired instructions per dump(4), on top of the
previous changes:
  canada  50.7M -> 44.4M (-13 %)   citm_catalog 8.85M -> 7.48M (-16 %)
  twitter 5.13M -> 4.71M (-8 %)    jeopardy 564M -> 518M (-8 %)
  a 139-byte object 3277 -> 2924 (-11 %)
Linux x86-64 (callgrind), the whole series against develop, gcc 13 / clang 18:
  canada, indent 4: -13 % / -14 %.

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

No files matched your search

+15
View File
@@ -31469,6 +31469,21 @@ class serializer
return;
}
// the usual indentation: four words of the indentation character are
// stored unconditionally and only the part wanted is claimed, which
// spares the call of memset
if (JSON_HEDLEY_LIKELY(indent <= 32 && write_buffer_pos + 32 <= write_buffer.size()))
{
const std::uint64_t word = 0x0101010101010101ull * static_cast<unsigned char>(indent_char);
char* const d = write_buffer.data() + write_buffer_pos;
std::memcpy(d, &word, sizeof(word));
std::memcpy(d + 8, &word, sizeof(word));
std::memcpy(d + 16, &word, sizeof(word));
std::memcpy(d + 24, &word, sizeof(word));
write_buffer_pos += indent;
return;
}
const std::size_t capacity = write_buffer.size();
// fill whatever room is left in the buffer; this is the whole job