mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2887e7432c | |||
| 764a6a0bb6 | |||
| 135eeecb40 |
Executable
+23
@@ -0,0 +1,23 @@
|
|||||||
|
CXX=clang++ cmake -B buildreflect -D SIMDJSON_STATIC_REFLECTION=ON -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_ABLATION_NO_BRANCH_HINTS=ON
|
||||||
|
cmake --build buildreflect --target benchmark_serialization_citm_catalog benchmark_serialization_twitter
|
||||||
|
./buildreflect/benchmark/static_reflect/citm_catalog_benchmark/benchmark_serialization_citm_catalog
|
||||||
|
./buildreflect/benchmark/static_reflect/twitter_benchmark/benchmark_serialization_twitter
|
||||||
|
|
||||||
|
|
||||||
|
CXX=clang++ cmake -B buildreflecthints -D SIMDJSON_STATIC_REFLECTION=ON -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_ABLATION_NO_BRANCH_HINTS=ON
|
||||||
|
cmake --build buildreflecthints --target benchmark_serialization_citm_catalog benchmark_serialization_twitter
|
||||||
|
./buildreflecthints/benchmark/static_reflect/citm_catalog_benchmark/benchmark_serialization_citm_catalog
|
||||||
|
./buildreflecthints/benchmark/static_reflect/twitter_benchmark/benchmark_serialization_twitter
|
||||||
|
|
||||||
|
|
||||||
|
CXX=clang++ cmake -B buildreflectescaping -D SIMDJSON_STATIC_REFLECTION=ON -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_ABLATION_NO_SIMD_ESCAPING=ON
|
||||||
|
cmake --build buildreflectescaping --target benchmark_serialization_citm_catalog benchmark_serialization_twitter
|
||||||
|
./buildreflectescaping/benchmark/static_reflect/citm_catalog_benchmark/benchmark_serialization_citm_catalog
|
||||||
|
./buildreflectescaping/benchmark/static_reflect/twitter_benchmark/benchmark_serialization_twitter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CXX=clang++ cmake -B buildreflectconsteval -D SIMDJSON_STATIC_REFLECTION=ON -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_ABLATION_NO_CONSTEVAL=ON
|
||||||
|
cmake --build buildreflectconsteval --target benchmark_serialization_citm_catalog benchmark_serialization_twitter
|
||||||
|
./buildreflectconsteval/benchmark/static_reflect/citm_catalog_benchmark/benchmark_serialization_citm_catalog
|
||||||
|
./buildreflectconsteval/benchmark/static_reflect/twitter_benchmark/benchmark_serialization_twitter
|
||||||
@@ -240,6 +240,36 @@ else()
|
|||||||
add_compile_definitions(SIMDJSON_UTF8VALIDATION=1)
|
add_compile_definitions(SIMDJSON_UTF8VALIDATION=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(
|
||||||
|
SIMDJSON_ABLATION_NO_BRANCH_HINTS
|
||||||
|
"Disable branch hints for ablation testing."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
if(SIMDJSON_ABLATION_NO_BRANCH_HINTS)
|
||||||
|
add_compile_definitions(ABLATION_NO_BRANCH_HINTS=1)
|
||||||
|
message(STATUS "ABLATION_NO_BRANCH_HINTS enabled")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(
|
||||||
|
SIMDJSON_ABLATION_NO_SIMD_ESCAPING
|
||||||
|
"Disable SIMD escaping for ablation testing."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
if(SIMDJSON_ABLATION_NO_SIMD_ESCAPING)
|
||||||
|
add_compile_definitions(ABLATION_NO_SIMD_ESCAPING=1)
|
||||||
|
message(STATUS "ABLATION_NO_SIMD_ESCAPING enabled")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(
|
||||||
|
SIMDJSON_ABLATION_NO_CONSTEVAL
|
||||||
|
"Disable consteval for ablation testing."
|
||||||
|
OFF
|
||||||
|
)
|
||||||
|
if(SIMDJSON_ABLATION_NO_CONSTEVAL)
|
||||||
|
add_compile_definitions(ABLATION_NO_CONSTEVAL=1)
|
||||||
|
message(STATUS "ABLATION_NO_CONSTEVAL enabled")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
check_symbol_exists(fork unistd.h HAVE_POSIX_FORK)
|
check_symbol_exists(fork unistd.h HAVE_POSIX_FORK)
|
||||||
check_symbol_exists(wait sys/wait.h HAVE_POSIX_WAIT)
|
check_symbol_exists(wait sys/wait.h HAVE_POSIX_WAIT)
|
||||||
|
|||||||
@@ -94,8 +94,12 @@ constexpr void atom(string_builder &b, const T &t) {
|
|||||||
template for (constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
|
template for (constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
b.append(',');
|
b.append(',');
|
||||||
|
#if ABLATION_NO_CONSTEVAL
|
||||||
|
b.escape_and_append_with_quotes(std::meta::identifier_of(dm));
|
||||||
|
#else
|
||||||
constexpr auto key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(dm)));
|
constexpr auto key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(dm)));
|
||||||
b.append_raw(key);
|
b.append_raw(key);
|
||||||
|
#endif
|
||||||
b.append(':');
|
b.append(':');
|
||||||
atom(b, t.[:dm:]);
|
atom(b, t.[:dm:]);
|
||||||
i++;
|
i++;
|
||||||
@@ -132,9 +136,13 @@ void atom(string_builder &b, const T &e) {
|
|||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
|
constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
|
||||||
template for (constexpr auto enum_val : enumerators) {
|
template for (constexpr auto enum_val : enumerators) {
|
||||||
constexpr auto enum_str = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(enum_val)));
|
|
||||||
if (e == [:enum_val:]) {
|
if (e == [:enum_val:]) {
|
||||||
|
#if ABLATION_NO_CONSTEVAL
|
||||||
|
b.escape_and_append_with_quotes(std::meta::identifier_of(enum_val));
|
||||||
|
#else
|
||||||
|
constexpr auto enum_str = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(enum_val)));
|
||||||
b.append_raw(enum_str);
|
b.append_raw(enum_str);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -229,8 +237,12 @@ void append(string_builder &b, const Z &z) {
|
|||||||
template for (constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^Z, std::meta::access_context::unchecked()))) {
|
template for (constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^Z, std::meta::access_context::unchecked()))) {
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
b.append(',');
|
b.append(',');
|
||||||
|
#if ABLATION_NO_CONSTEVAL
|
||||||
|
b.escape_and_append_with_quotes(std::meta::identifier_of(dm));
|
||||||
|
#else
|
||||||
constexpr auto key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(dm)));
|
constexpr auto key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(dm)));
|
||||||
b.append_raw(key);
|
b.append_raw(key);
|
||||||
|
#endif
|
||||||
b.append(':');
|
b.append(':');
|
||||||
atom(b, z.[:dm:]);
|
atom(b, z.[:dm:]);
|
||||||
i++;
|
i++;
|
||||||
@@ -317,8 +329,12 @@ void extract_from(string_builder &b, const T &obj) {
|
|||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
// Serialize the key
|
// Serialize the key
|
||||||
|
#if ABLATION_NO_CONSTEVAL
|
||||||
|
b.escape_and_append_with_quotes(std::meta::identifier_of(mem));
|
||||||
|
#else
|
||||||
constexpr auto quoted_key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)));
|
constexpr auto quoted_key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)));
|
||||||
b.append_raw(quoted_key);
|
b.append_raw(quoted_key);
|
||||||
|
#endif
|
||||||
b.append(':');
|
b.append(':');
|
||||||
|
|
||||||
// Serialize the value
|
// Serialize the value
|
||||||
|
|||||||
@@ -295,9 +295,22 @@ SIMDJSON_CONSTEXPR_LAMBDA simdjson_inline void escape_json_char(char c, char *&o
|
|||||||
// written. Uses SIMD position finding to locate quotable characters efficiently.
|
// written. Uses SIMD position finding to locate quotable characters efficiently.
|
||||||
inline size_t write_string_escaped(const std::string_view input, char *out) {
|
inline size_t write_string_escaped(const std::string_view input, char *out) {
|
||||||
size_t mysize = input.size();
|
size_t mysize = input.size();
|
||||||
|
#if ABLATION_NO_SIMD_ESCAPING
|
||||||
|
auto naive_find_next_json_quotable_character = [](std::string_view input, size_t start) -> size_t {
|
||||||
|
for (size_t i = start; i < input.size(); ++i) {
|
||||||
|
auto c = static_cast<unsigned char>(input[i]);
|
||||||
|
if (c == '"' || c == '\\' || c < 32) return i;
|
||||||
|
}
|
||||||
|
return input.size();
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// Use SIMD position finder directly - it returns mysize if no escape needed
|
// Use SIMD position finder directly - it returns mysize if no escape needed
|
||||||
|
#if ABLATION_NO_SIMD_ESCAPING
|
||||||
|
size_t location = naive_find_next_json_quotable_character(input, 0);
|
||||||
|
#else
|
||||||
size_t location = find_next_json_quotable_character(input, 0);
|
size_t location = find_next_json_quotable_character(input, 0);
|
||||||
|
#endif
|
||||||
if (location == mysize) {
|
if (location == mysize) {
|
||||||
// Fast path: no escaping needed
|
// Fast path: no escaping needed
|
||||||
memcpy(out, input.data(), input.size());
|
memcpy(out, input.data(), input.size());
|
||||||
@@ -310,7 +323,11 @@ inline size_t write_string_escaped(const std::string_view input, char *out) {
|
|||||||
escape_json_char(input[location], out);
|
escape_json_char(input[location], out);
|
||||||
location += 1;
|
location += 1;
|
||||||
while (location < mysize) {
|
while (location < mysize) {
|
||||||
|
#if ABLATION_NO_SIMD_ESCAPING
|
||||||
|
size_t newlocation = naive_find_next_json_quotable_character(input, location);
|
||||||
|
#else
|
||||||
size_t newlocation = find_next_json_quotable_character(input, location);
|
size_t newlocation = find_next_json_quotable_character(input, location);
|
||||||
|
#endif
|
||||||
memcpy(out, input.data() + location, newlocation - location);
|
memcpy(out, input.data() + location, newlocation - location);
|
||||||
out += newlocation - location;
|
out += newlocation - location;
|
||||||
location = newlocation;
|
location = newlocation;
|
||||||
@@ -332,13 +349,23 @@ simdjson_inline bool string_builder::capacity_check(size_t upcoming_bytes) {
|
|||||||
// We use the convention that when is_valid is false, then the capacity and
|
// We use the convention that when is_valid is false, then the capacity and
|
||||||
// the position are 0.
|
// the position are 0.
|
||||||
// Most of the time, this function will return true.
|
// Most of the time, this function will return true.
|
||||||
|
#if ABLATION_NO_BRANCH_HINTS
|
||||||
|
if (upcoming_bytes <= capacity - position) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// check for overflow, most of the time there is no overflow
|
||||||
|
if (position + upcoming_bytes < position) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (simdjson_likely(upcoming_bytes <= capacity - position)) {
|
if (simdjson_likely(upcoming_bytes <= capacity - position)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// check for overflow, most of the time there is no overflow
|
// check for overflow, most of the time there is no overflow
|
||||||
if (simdjson_likely(position + upcoming_bytes < position)) {
|
if (simdjson_unlikely(position + upcoming_bytes < position)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// We will rarely get here.
|
// We will rarely get here.
|
||||||
grow_buffer((std::max)(capacity * 2, position + upcoming_bytes));
|
grow_buffer((std::max)(capacity * 2, position + upcoming_bytes));
|
||||||
// If the buffer allocation failed, we set is_valid to false.
|
// If the buffer allocation failed, we set is_valid to false.
|
||||||
|
|||||||
Reference in New Issue
Block a user