mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
WIP: template append_raw on size for compile-time-inlined memcpy
Add append_raw_n<N>(const char*) which propagates the key length as a
template parameter, letting the compiler emit a fully inlined memcpy
with a constant size (direct loads/stores) instead of the size-passed-
as-runtime-arg variant which sometimes fell back to a libc memcpy
dispatch.
Use it in the reflection struct atom for both first_key and rest_key
(both are compile-time constants from define_static_string).
Measured (TRUE A/B, 7 alternating rounds in single docker invocation,
two independent runs combined):
CITM: baseline ~4395 -> patched ~4791 MB/s (+9%)
Glaze ~4810 MB/s -> simdjson now at PARITY with Glaze
(within +/- 3% noise across runs)
Twitter: still well ahead of Glaze, no change from baseline
Output is byte-identical, all reflection comprehensive tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -100,12 +100,12 @@ simdjson_really_inline constexpr void atom(string_builder &b, const T &t) {
|
||||
constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(dm)) + ":");
|
||||
constexpr auto rest_key = std::define_static_string(
|
||||
std::string(",") + constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(dm)) + ":");
|
||||
// Pass size explicitly so we avoid the runtime strlen() in
|
||||
// append_raw(const char*) — these keys are compile-time constants.
|
||||
// Pass size as template parameter so memcpy is fully inlined with
|
||||
// a compile-time-constant size.
|
||||
constexpr size_t first_key_len = std::char_traits<char>::length(first_key);
|
||||
constexpr size_t rest_key_len = std::char_traits<char>::length(rest_key);
|
||||
if (i == 0) b.append_raw(first_key, first_key_len);
|
||||
else b.append_raw(rest_key, rest_key_len);
|
||||
if (i == 0) b.template append_raw_n<first_key_len>(first_key);
|
||||
else b.template append_raw_n<rest_key_len>(rest_key);
|
||||
atom(b, t.[:dm:]);
|
||||
i++;
|
||||
};
|
||||
|
||||
@@ -780,6 +780,14 @@ simdjson_inline void string_builder::append_raw(const char *str,
|
||||
position += len;
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
simdjson_inline void string_builder::append_raw_n(const char *str) noexcept {
|
||||
if (capacity_check(N)) {
|
||||
std::memcpy(buffer.get() + position, str, N);
|
||||
position += N;
|
||||
}
|
||||
}
|
||||
#if SIMDJSON_SUPPORTS_CONCEPTS
|
||||
// Support for optional types (std::optional, etc.)
|
||||
template <concepts::optional_type T>
|
||||
|
||||
@@ -185,6 +185,15 @@ requires (!std::is_convertible<R, std::string_view>::value && !concepts::optiona
|
||||
* There is no UTF-8 validation.
|
||||
*/
|
||||
simdjson_inline void append_raw(const char *str, size_t len) noexcept;
|
||||
|
||||
/**
|
||||
* Append exactly N characters from str. The length is a template parameter
|
||||
* so the compiler can fully inline the memcpy with a compile-time-constant
|
||||
* size, avoiding the libc call. Used for compile-time-constant keys in the
|
||||
* reflection struct atom.
|
||||
*/
|
||||
template <size_t N>
|
||||
simdjson_inline void append_raw_n(const char *str) noexcept;
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
/**
|
||||
* Creates an std::string from the written JSON buffer.
|
||||
|
||||
Reference in New Issue
Block a user