Skip to content

Commit 76b8c78

Browse files
Merge pull request #30 from simdjson/disable_reflect_cpp
reflect cpp does not build under LLVM 19, disable by default
2 parents 6c920dc + ec65450 commit 76b8c78

9 files changed

Lines changed: 139 additions & 83 deletions

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ CPMAddPackage("gh:nlohmann/json@3.10.5")
2424
CPMAddPackage(
2525
NAME reflect-cpp
2626
GITHUB_REPOSITORY getml/reflect-cpp
27-
GIT_TAG main
27+
GIT_TAG v0.13.0
2828
)
2929

3030
# Optionally, specify the C++ compiler directly (here we use clang++)

benchmarks/src/CMakeLists.txt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,31 @@ add_executable(SerializationTwitterBenchmark benchmark_serialization_twitter.cpp
5656
target_compile_options(SerializationBenchmark PRIVATE -freflection -stdlib=libc++ -std=c++26)
5757
target_compile_options(SerializationTwitterBenchmark PRIVATE -freflection -stdlib=libc++ -std=c++26)
5858

59-
#find_package(CURL REQUIRED)
6059

6160
# Link sanitizers and libraries
62-
target_link_libraries(SerializationTwitterBenchmark PRIVATE nlohmann_json::nlohmann_json simdjson::simdjson reflectcpp)
63-
target_link_libraries(SerializationBenchmark PRIVATE simdjson-serial nlohmann_json::nlohmann_json simdjson::simdjson reflectcpp)
61+
target_link_libraries(SerializationTwitterBenchmark PRIVATE nlohmann_json::nlohmann_json simdjson::simdjson )
62+
63+
target_link_libraries(SerializationBenchmark PRIVATE simdjson-serial nlohmann_json::nlohmann_json simdjson::simdjson)
64+
65+
# cpp-reflect may fail to build on LLVM 19 due to this issue
66+
# https://github.com/hanickadot/compile-time-regular-expressions/issues/307
67+
option(SIMDJSON_BENCH_CPP_REFLECT "include cpp reflect in the benchmarks" OFF)
68+
if(SIMDJSON_BENCH_CPP_REFLECT)
69+
message(STATUS "Including reflect-cpp in the benchmarks.")
70+
add_library(benchmark_reflect_serialization_twitter STATIC benchmark_reflect_serialization_twitter.cpp)
71+
target_link_libraries(benchmark_reflect_serialization_twitter PRIVATE reflectcpp)
72+
73+
target_link_libraries(SerializationTwitterBenchmark PRIVATE benchmark_reflect_serialization_twitter)
74+
target_compile_definitions(SerializationTwitterBenchmark PRIVATE SIMDJSON_BENCH_CPP_REFLECT=1)
75+
76+
77+
add_library(benchmark_reflect_serialization STATIC benchmark_reflect_serialization_twitter.cpp)
78+
target_link_libraries(benchmark_reflect_serialization PRIVATE reflectcpp)
79+
80+
target_link_libraries(SerializationBenchmark PRIVATE benchmark_reflect_serialization)
81+
target_compile_definitions(SerializationBenchmark PRIVATE SIMDJSON_BENCH_CPP_REFLECT=1)
82+
endif()
83+
84+
6485

6586
target_compile_definitions(SerializationTwitterBenchmark PRIVATE JSON_FILE="${CMAKE_CURRENT_SOURCE_DIR}/data/twitter.json")
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#ifndef BENCHMARK_HELPER_HPP
2+
#define BENCHMARK_HELPER_HPP
3+
#include "event_counter.h"
4+
5+
inline event_collector& get_collector() {
6+
static event_collector collector;
7+
return collector;
8+
}
9+
10+
template <class function_type>
11+
event_aggregate bench(const function_type &function, size_t min_repeat = 10,
12+
size_t min_time_ns = 1000000000,
13+
size_t max_repeat = 100000) {
14+
event_collector& collector = get_collector();
15+
event_aggregate aggregate{};
16+
size_t N = min_repeat;
17+
if (N == 0) {
18+
N = 1;
19+
}
20+
for (size_t i = 0; i < N; i++) {
21+
std::atomic_thread_fence(std::memory_order_acquire);
22+
collector.start();
23+
function();
24+
std::atomic_thread_fence(std::memory_order_release);
25+
event_count allocate_count = collector.end();
26+
aggregate << allocate_count;
27+
if ((i + 1 == N) && (aggregate.total_elapsed_ns() < min_time_ns) &&
28+
(N < max_repeat)) {
29+
N *= 10;
30+
}
31+
}
32+
return aggregate;
33+
}
34+
35+
// Source of the 2 functions below:
36+
// https://github.com/simdutf/simdutf/blob/master/benchmarks/base64/benchmark_base64.cpp
37+
inline void pretty_print(size_t strings, size_t bytes, std::string name, event_aggregate agg) {
38+
event_collector& collector = get_collector();
39+
printf("%-60s : ", name.c_str());
40+
printf(" %5.2f MB/s ", bytes * 1000 / agg.elapsed_ns());
41+
printf(" %5.2f Ms/s ", strings * 1000 / agg.elapsed_ns());
42+
if (collector.has_events()) {
43+
printf(" %5.2f GHz ", agg.cycles() / agg.elapsed_ns());
44+
printf(" %5.2f c/b ", agg.cycles() / bytes);
45+
printf(" %5.2f i/b ", agg.instructions() / bytes);
46+
printf(" %5.2f i/c ", agg.instructions() / agg.cycles());
47+
}
48+
printf("\n");
49+
}
50+
#endif
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "benchmark_reflect_serialization.hpp"
2+
#include "benchmark_helper.hpp"
3+
4+
#include <rfl.hpp>
5+
#include <rfl/json.hpp>
6+
7+
void bench_reflect_cpp(std::vector<User>& data) {
8+
std::string output = rfl::json::write(data);
9+
size_t output_volume = output.size();
10+
printf("# output volume: %zu bytes\n", output_volume);
11+
12+
volatile size_t measured_volume = 0;
13+
pretty_print(
14+
1, output_volume, "bench_reflect_cpp",
15+
bench([&data, &measured_volume, &output_volume] () {
16+
std::string output = rfl::json::write(data);
17+
measured_volume = output.size();
18+
if(measured_volume != output_volume) { printf("mismatch\n"); }
19+
})
20+
);
21+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef BENCHMARK_REFLECT_SERIALIZATION_TWITTER_HPP
2+
#define BENCHMARK_REFLECT_SERIALIZATION_TWITTER_HPP
3+
4+
#include "user_profile.hpp"
5+
void bench_reflect_cpp(std::vector<User>& data)
6+
#endif
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "benchmark_reflect_serialization_twitter.hpp"
2+
#include "benchmark_helper.hpp"
3+
4+
#include <rfl.hpp>
5+
#include <rfl/json.hpp>
6+
void bench_reflect_cpp(TwitterData& data) {
7+
std::string output = rfl::json::write(data);
8+
size_t output_volume = output.size();
9+
printf("# output volume: %zu bytes\n", output_volume);
10+
11+
volatile size_t measured_volume = 0;
12+
pretty_print(
13+
1, output_volume, "bench_reflect_cpp",
14+
bench([&data, &measured_volume, &output_volume] () {
15+
std::string output = rfl::json::write(data);
16+
measured_volume = output.size();
17+
if(measured_volume != output_volume) { printf("mismatch\n"); }
18+
})
19+
);
20+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef BENCHMARK_REFLECT_SERIALIZATION_TWITTER_HPP
2+
#define BENCHMARK_REFLECT_SERIALIZATION_TWITTER_HPP
3+
4+
#include "twitter_data.hpp"
5+
void bench_reflect_cpp(TwitterData& data);
6+
#endif

benchmarks/src/benchmark_serialization.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
#include <vector>
1111
#include <format>
1212
#include <atomic>
13-
#include <rfl.hpp>
14-
#include <rfl/json.hpp>
1513
#include "user_profile.hpp"
1614
#include "custom_serializer.h"
1715
#include "nlohmann_user_profile.hpp"
18-
16+
#if SIMDJSON_BENCH_CPP_REFLECT
17+
#include "benchmark_reflect_serialization.hpp"
18+
#endif
1919
std::string generate_email(const std::string &name,
2020
const std::string &company) {
2121
std::string email = name + "@" + company + ".com";
@@ -231,21 +231,6 @@ void bench_nlohmann(std::vector<User> &data) {
231231
);
232232
}
233233

234-
void bench_reflect_cpp(std::vector<User>& data) {
235-
std::string output = rfl::json::write(data);
236-
size_t output_volume = output.size();
237-
printf("# output volume: %zu bytes\n", output_volume);
238-
239-
volatile size_t measured_volume = 0;
240-
pretty_print(
241-
1, output_volume, "bench_reflect_cpp",
242-
bench([&data, &measured_volume, &output_volume] () {
243-
std::string output = rfl::json::write(data);
244-
measured_volume = output.size();
245-
if(measured_volume != output_volume) { printf("mismatch\n"); }
246-
})
247-
);
248-
}
249234

250235

251236
int main() {
@@ -257,7 +242,8 @@ int main() {
257242
bench_nlohmann(test_data);
258243
bench_custom(test_data);
259244
bench_fast_simpler(test_data);
245+
#if SIMDJSON_BENCH_CPP_REFLECT
260246
bench_reflect_cpp(test_data);
261-
247+
#endif
262248
return EXIT_SUCCESS;
263249
}

benchmarks/src/benchmark_serialization_twitter.cpp

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "../../src/from_json.hpp"
22
#include "twitter_data.hpp"
33
#include "nlohmann_twitter_data.hpp"
4-
#include "event_counter.h"
54
#include <cassert>
65
#include <cstdlib>
76
#include <ctime>
@@ -12,49 +11,10 @@
1211
#include <simdjson.h>
1312
#include <fstream>
1413
#include <nlohmann/json.hpp>
15-
#include <rfl.hpp>
16-
#include <rfl/json.hpp>
17-
18-
event_collector collector;
19-
20-
template <class function_type>
21-
event_aggregate bench(const function_type &function, size_t min_repeat = 10,
22-
size_t min_time_ns = 1000000000,
23-
size_t max_repeat = 100000) {
24-
event_aggregate aggregate{};
25-
size_t N = min_repeat;
26-
if (N == 0) {
27-
N = 1;
28-
}
29-
for (size_t i = 0; i < N; i++) {
30-
std::atomic_thread_fence(std::memory_order_acquire);
31-
collector.start();
32-
function();
33-
std::atomic_thread_fence(std::memory_order_release);
34-
event_count allocate_count = collector.end();
35-
aggregate << allocate_count;
36-
if ((i + 1 == N) && (aggregate.total_elapsed_ns() < min_time_ns) &&
37-
(N < max_repeat)) {
38-
N *= 10;
39-
}
40-
}
41-
return aggregate;
42-
}
43-
44-
// Source of the 2 functions below:
45-
// https://github.com/simdutf/simdutf/blob/master/benchmarks/base64/benchmark_base64.cpp
46-
void pretty_print(size_t strings, size_t bytes, std::string name, event_aggregate agg) {
47-
printf("%-60s : ", name.c_str());
48-
printf(" %5.2f MB/s ", bytes * 1000 / agg.elapsed_ns());
49-
printf(" %5.2f Ms/s ", strings * 1000 / agg.elapsed_ns());
50-
if (collector.has_events()) {
51-
printf(" %5.2f GHz ", agg.cycles() / agg.elapsed_ns());
52-
printf(" %5.2f c/b ", agg.cycles() / bytes);
53-
printf(" %5.2f i/b ", agg.instructions() / bytes);
54-
printf(" %5.2f i/c ", agg.instructions() / agg.cycles());
55-
}
56-
printf("\n");
57-
}
14+
#include "benchmark_helper.hpp"
15+
#if SIMDJSON_BENCH_CPP_REFLECT
16+
#include "benchmark_reflect_serialization_twitter.hpp"
17+
#endif
5818

5919
template <class T>
6020
void bench_fast_simpler(T &data) {
@@ -92,21 +52,6 @@ void bench_nlohmann(TwitterData &data) {
9252
);
9353
}
9454

95-
void bench_reflect_cpp(TwitterData& data) {
96-
std::string output = rfl::json::write(data);
97-
size_t output_volume = output.size();
98-
printf("# output volume: %zu bytes\n", output_volume);
99-
100-
volatile size_t measured_volume = 0;
101-
pretty_print(
102-
1, output_volume, "bench_reflect_cpp",
103-
bench([&data, &measured_volume, &output_volume] () {
104-
std::string output = rfl::json::write(data);
105-
measured_volume = output.size();
106-
if(measured_volume != output_volume) { printf("mismatch\n"); }
107-
})
108-
);
109-
}
11055

11156
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
11257
((std::string*)userp)->append((char*)contents, size * nmemb);
@@ -233,7 +178,8 @@ int main()
233178
experimental_json_builder::from_json(json_value, my_struct);
234179
bench_fast_simpler(my_struct);
235180
bench_nlohmann(my_struct);
181+
#if SIMDJSON_BENCH_CPP_REFLECT
236182
bench_reflect_cpp(my_struct);
237-
183+
#endif
238184
return EXIT_SUCCESS;
239185
}

0 commit comments

Comments
 (0)