22#include < chrono>
33#include < iostream>
44#include < string>
5+ #include < vector>
6+ #include < variant>
57
68using Clock = std::chrono::high_resolution_clock;
79
@@ -11,38 +13,9 @@ static void print_header(const std::string &title) {
1113 std::cout << std::string (100 , ' =' ) << " \n\n " ;
1214}
1315
14- static void print_object (simdjson::ondemand::object obj) {
15- std::cout << " {" ;
16- bool first = true ;
17- for (auto field : obj) {
18- if (!first) std::cout << " , " ;
19- first = false ;
20-
21- std::string_view key = field.unescaped_key ();
22- simdjson::ondemand::value val = field.value ();
23-
24- std::cout << " \" " << key << " \" => " ;
25-
26- // Print values similar to Ruby's inspect
27- switch (val.type ()) {
28- case simdjson::ondemand::json_type::number:
29- std::cout << double (val);
30- break ;
31- case simdjson::ondemand::json_type::string:
32- std::cout << " \" " << std::string (val.get_string ().value ()) << " \" " ;
33- break ;
34- case simdjson::ondemand::json_type::boolean:
35- std::cout << (bool (val) ? " true" : " false" );
36- break ;
37- case simdjson::ondemand::json_type::null:
38- std::cout << " nil" ;
39- break ;
40- default :
41- std::cout << " <complex>" ;
42- }
43- }
44- std::cout << " }" ;
45- }
16+ struct Value {
17+ std::variant<double , std::string, bool , std::nullptr_t > data;
18+ };
4619
4720int main (int argc, char **argv) {
4821 const char *filename = " twitter.json" ;
@@ -53,80 +26,137 @@ int main(int argc, char **argv) {
5326
5427 // Load file
5528 simdjson::padded_string json = simdjson::padded_string::load (filename);
56-
5729 std::cout << " File: " << filename << " (" << json.size () << " bytes)\n\n " ;
5830
5931 // EAGER DECODE
6032 print_header (" EAGER DECODE BENCHMARK (twitter.json)" );
61-
6233 {
6334 std::cout << " simdjson DOM parse\n " ;
6435 auto start = Clock::now ();
65-
6636 simdjson::dom::element doc;
6737 dom_parser.parse (json).get (doc);
68-
6938 auto end = Clock::now ();
7039 double elapsed = std::chrono::duration<double >(end - start).count ();
7140 double ops = 1.0 / elapsed;
72-
7341 std::cout << " Time: " << elapsed << " sec\n " ;
7442 std::cout << " OPS: " << ops << " \n\n " ;
7543 }
7644
7745 // LAZY DECODE
7846 print_header (" LAZY DECODE BENCHMARK — /search_metadata" );
79-
8047 {
8148 std::cout << " simdjson On-Demand\n " ;
8249 auto start = Clock::now ();
83-
8450 simdjson::ondemand::document doc = ondemand_parser.iterate(json);
8551 simdjson::ondemand::object root = doc.get_object ();
8652 simdjson::ondemand::object sm = root[" search_metadata" ];
87-
53+ // Materialize all fields (equivalent to mruby .value)
54+ std::vector<std::pair<std::string, Value>> fields;
55+ for (auto field : sm) {
56+ std::string key (field.unescaped_key ());
57+ simdjson::ondemand::value val = field.value ();
58+ Value v;
59+ switch (val.type ()) {
60+ case simdjson::ondemand::json_type::number:
61+ v.data = double (val);
62+ break ;
63+ case simdjson::ondemand::json_type::string:
64+ v.data = std::string (val.get_string ().value ());
65+ break ;
66+ case simdjson::ondemand::json_type::boolean:
67+ v.data = bool (val);
68+ break ;
69+ case simdjson::ondemand::json_type::null:
70+ v.data = nullptr ;
71+ break ;
72+ default :
73+ break ;
74+ }
75+ fields.emplace_back (std::move (key), std::move (v));
76+ }
8877 auto end = Clock::now ();
8978 double elapsed = std::chrono::duration<double >(end - start).count ();
9079 double ops = 1.0 / elapsed;
91-
92- std::cout << " Result: " ;
93- print_object (sm);
94- std::cout << " \n " ;
95-
80+ // Print result
81+ std::cout << " Result: {" ;
82+ bool first = true ;
83+ for (auto &[k, v] : fields) {
84+ if (!first) std::cout << " , " ;
85+ first = false ;
86+ std::cout << " \" " << k << " \" => " ;
87+ std::visit ([](auto &&arg) {
88+ using T = std::decay_t <decltype (arg)>;
89+ if constexpr (std::is_same_v<T, double >) std::cout << arg;
90+ else if constexpr (std::is_same_v<T, std::string>) std::cout << " \" " << arg << " \" " ;
91+ else if constexpr (std::is_same_v<T, bool >) std::cout << (arg ? " true" : " false" );
92+ else if constexpr (std::is_same_v<T, std::nullptr_t >) std::cout << " nil" ;
93+ }, v.data );
94+ }
95+ std::cout << " }\n " ;
9696 std::cout << " Time: " << elapsed << " sec\n " ;
9797 std::cout << " OPS: " << ops << " \n\n " ;
9898 }
99-
10099 {
101100 std::cout << " simdjson DOM (parse + /search_metadata)\n " ;
102101 auto start = Clock::now ();
103-
104102 simdjson::dom::element doc;
105103 dom_parser.parse (json).get (doc);
106-
107104 simdjson::dom::object root = doc.get_object ();
108105 simdjson::dom::object sm = root[" search_metadata" ];
109-
106+ // Materialize all fields
107+ std::vector<std::pair<std::string, Value>> fields;
108+ for (auto field : sm) {
109+ std::string key (field.key );
110+ Value v;
111+ switch (field.value .type ()) {
112+ case simdjson::dom::element_type::DOUBLE:
113+ v.data = double (field.value );
114+ break ;
115+ case simdjson::dom::element_type::INT64:
116+ v.data = double (int64_t (field.value ));
117+ break ;
118+ case simdjson::dom::element_type::UINT64:
119+ v.data = double (uint64_t (field.value ));
120+ break ;
121+ case simdjson::dom::element_type::STRING:
122+ v.data = std::string (std::string_view (field.value ));
123+ break ;
124+ case simdjson::dom::element_type::BOOL:
125+ v.data = bool (field.value );
126+ break ;
127+ case simdjson::dom::element_type::NULL_VALUE:
128+ v.data = nullptr ;
129+ break ;
130+ default :
131+ break ;
132+ }
133+ fields.emplace_back (std::move (key), std::move (v));
134+ }
110135 auto end = Clock::now ();
111136 double elapsed = std::chrono::duration<double >(end - start).count ();
112137 double ops = 1.0 / elapsed;
113-
138+ // Print result
114139 std::cout << " Result: {" ;
115140 bool first = true ;
116- for (auto field : sm ) {
141+ for (auto &[k, v] : fields ) {
117142 if (!first) std::cout << " , " ;
118143 first = false ;
119- std::cout << " \" " << std::string (field.key ) << " \" => " << field.value ;
144+ std::cout << " \" " << k << " \" => " ;
145+ std::visit ([](auto &&arg) {
146+ using T = std::decay_t <decltype (arg)>;
147+ if constexpr (std::is_same_v<T, double >) std::cout << arg;
148+ else if constexpr (std::is_same_v<T, std::string>) std::cout << " \" " << arg << " \" " ;
149+ else if constexpr (std::is_same_v<T, bool >) std::cout << (arg ? " true" : " false" );
150+ else if constexpr (std::is_same_v<T, std::nullptr_t >) std::cout << " nil" ;
151+ }, v.data );
120152 }
121153 std::cout << " }\n " ;
122-
123154 std::cout << " Time: " << elapsed << " sec\n " ;
124155 std::cout << " OPS: " << ops << " \n\n " ;
125156 }
126157
127158 std::cout << std::string (100 , ' =' ) << " \n " ;
128159 std::cout << " Done.\n " ;
129160 std::cout << std::string (100 , ' =' ) << " \n " ;
130-
131161 return 0 ;
132162}
0 commit comments