@@ -75,7 +75,6 @@ void exit_usage(string message) {
75
75
}
76
76
77
77
struct option_struct {
78
- architecture arch = architecture::UNSUPPORTED;
79
78
bool stage1_only = false ;
80
79
81
80
int32_t iterations = 400 ;
@@ -98,10 +97,7 @@ struct option_struct {
98
97
verbose = true ;
99
98
break ;
100
99
case ' a' :
101
- arch = parse_architecture (optarg );
102
- if (arch == architecture::UNSUPPORTED) {
103
- exit_usage (string (" Unsupported option value -a " ) + optarg + " : expected -a HASWELL, WESTMERE or ARM64" );
104
- }
100
+ simdjson::active_implementation = simdjson::available_implementations[optarg ];
105
101
break ;
106
102
case ' s' :
107
103
if (!strcmp (optarg , " stage1" )) {
@@ -113,15 +109,9 @@ struct option_struct {
113
109
}
114
110
break ;
115
111
default :
116
- exit_error (" Unexpected argument " + c );
112
+ exit_error (string ( " Unexpected argument " ) + std::string ( 1 , static_cast < char >(c)) );
117
113
}
118
114
}
119
-
120
- // If architecture is not specified, pick the best supported architecture by default
121
- if (arch == architecture::UNSUPPORTED) {
122
- arch = find_best_supported_architecture ();
123
- }
124
- dom::parser::use_implementation (arch);
125
115
}
126
116
127
117
template <typename F>
@@ -150,20 +140,20 @@ struct feature_benchmarker {
150
140
benchmarker struct23;
151
141
benchmarker struct23_miss;
152
142
153
- feature_benchmarker (const simdjson::implementation &parser, event_collector& collector) :
154
- utf8 (" jsonexamples/ generated/utf-8.json" , parser , collector),
155
- utf8_miss (" jsonexamples/ generated/utf-8-miss.json" , parser , collector),
156
- escape (" jsonexamples/ generated/escape.json" , parser , collector),
157
- escape_miss (" jsonexamples/ generated/escape-miss.json" , parser , collector),
158
- empty (" jsonexamples/ generated/0-structurals.json" , parser , collector),
159
- empty_miss (" jsonexamples/ generated/0-structurals-miss.json" , parser , collector),
160
- struct7 (" jsonexamples/ generated/7-structurals.json" , parser , collector),
161
- struct7_miss (" jsonexamples/ generated/7-structurals-miss.json" , parser , collector),
162
- struct7_full (" jsonexamples/ generated/7-structurals-full.json" , parser , collector),
163
- struct15 (" jsonexamples/ generated/15-structurals.json" , parser , collector),
164
- struct15_miss (" jsonexamples/ generated/15-structurals-miss.json" , parser , collector),
165
- struct23 (" jsonexamples/ generated/23-structurals.json" , parser , collector),
166
- struct23_miss (" jsonexamples/ generated/23-structurals-miss.json" , parser , collector)
143
+ feature_benchmarker (event_collector& collector) :
144
+ utf8 (SIMDJSON_BENCHMARK_DATA_DIR " generated/utf-8.json" , collector),
145
+ utf8_miss (SIMDJSON_BENCHMARK_DATA_DIR " generated/utf-8-miss.json" , collector),
146
+ escape (SIMDJSON_BENCHMARK_DATA_DIR " generated/escape.json" , collector),
147
+ escape_miss (SIMDJSON_BENCHMARK_DATA_DIR " generated/escape-miss.json" , collector),
148
+ empty (SIMDJSON_BENCHMARK_DATA_DIR " generated/0-structurals.json" , collector),
149
+ empty_miss (SIMDJSON_BENCHMARK_DATA_DIR " generated/0-structurals-miss.json" , collector),
150
+ struct7 (SIMDJSON_BENCHMARK_DATA_DIR " generated/7-structurals.json" , collector),
151
+ struct7_miss (SIMDJSON_BENCHMARK_DATA_DIR " generated/7-structurals-miss.json" , collector),
152
+ struct7_full (SIMDJSON_BENCHMARK_DATA_DIR " generated/7-structurals-full.json" , collector),
153
+ struct15 (SIMDJSON_BENCHMARK_DATA_DIR " generated/15-structurals.json" , collector),
154
+ struct15_miss (SIMDJSON_BENCHMARK_DATA_DIR " generated/15-structurals-miss.json" , collector),
155
+ struct23 (SIMDJSON_BENCHMARK_DATA_DIR " generated/23-structurals.json" , collector),
156
+ struct23_miss (SIMDJSON_BENCHMARK_DATA_DIR " generated/23-structurals-miss.json" , collector)
167
157
{
168
158
169
159
}
@@ -185,7 +175,7 @@ struct feature_benchmarker {
185
175
}
186
176
187
177
double cost_per_block (BenchmarkStage stage, const benchmarker& feature, size_t feature_blocks, const benchmarker& base) const {
188
- return (feature[stage].best .elapsed_ns () - base[stage].best .elapsed_ns ()) / feature_blocks;
178
+ return (feature[stage].best .elapsed_ns () - base[stage].best .elapsed_ns ()) / double ( feature_blocks) ;
189
179
}
190
180
191
181
// Whether we're recording cache miss and branch miss events
@@ -195,7 +185,7 @@ struct feature_benchmarker {
195
185
196
186
// Base cost of any block (including empty ones)
197
187
double base_cost (BenchmarkStage stage) const {
198
- return (empty[stage].best .elapsed_ns () / empty.stats ->blocks );
188
+ return (empty[stage].best .elapsed_ns () / double ( empty.stats ->blocks ) );
199
189
}
200
190
201
191
// Extra cost of a 1-7 structural block over an empty block
@@ -209,7 +199,7 @@ struct feature_benchmarker {
209
199
// Rate of 1-7-structural misses per 8-structural flip
210
200
double struct1_7_miss_rate (BenchmarkStage stage) const {
211
201
if (!has_events ()) { return 1 ; }
212
- return double ( struct7_miss[stage].best .branch_misses () - struct7[stage].best .branch_misses ()) / struct7_miss.stats ->blocks_with_1_structural_flipped ;
202
+ return struct7_miss[stage].best .branch_misses () - struct7[stage].best .branch_misses () / double ( struct7_miss.stats ->blocks_with_1_structural_flipped ) ;
213
203
}
214
204
215
205
// Extra cost of an 8-15 structural block over a 1-7 structural block
@@ -223,7 +213,7 @@ struct feature_benchmarker {
223
213
// Rate of 8-15-structural misses per 8-structural flip
224
214
double struct8_15_miss_rate (BenchmarkStage stage) const {
225
215
if (!has_events ()) { return 1 ; }
226
- return double (struct15_miss[stage].best .branch_misses () - struct15[stage].best .branch_misses ()) / struct15_miss.stats ->blocks_with_8_structurals_flipped ;
216
+ return double (struct15_miss[stage].best .branch_misses () - struct15[stage].best .branch_misses ()) / double ( struct15_miss.stats ->blocks_with_8_structurals_flipped ) ;
227
217
}
228
218
229
219
// Extra cost of a 16+-structural block over an 8-15 structural block (actual varies based on # of structurals!)
@@ -237,7 +227,7 @@ struct feature_benchmarker {
237
227
// Rate of 16-structural misses per 16-structural flip
238
228
double struct16_miss_rate (BenchmarkStage stage) const {
239
229
if (!has_events ()) { return 1 ; }
240
- return double (struct23_miss[stage].best .branch_misses () - struct23[stage].best .branch_misses ()) / struct23_miss.stats ->blocks_with_16_structurals_flipped ;
230
+ return double (struct23_miss[stage].best .branch_misses () - struct23[stage].best .branch_misses ()) / double ( struct23_miss.stats ->blocks_with_16_structurals_flipped ) ;
241
231
}
242
232
243
233
// Extra cost of having UTF-8 in a block
@@ -251,7 +241,7 @@ struct feature_benchmarker {
251
241
// Rate of UTF-8 misses per UTF-8 flip
252
242
double utf8_miss_rate (BenchmarkStage stage) const {
253
243
if (!has_events ()) { return 1 ; }
254
- return double (utf8_miss[stage].best .branch_misses () - utf8[stage].best .branch_misses ()) / utf8_miss.stats ->blocks_with_utf8_flipped ;
244
+ return double (utf8_miss[stage].best .branch_misses () - utf8[stage].best .branch_misses ()) / double ( utf8_miss.stats ->blocks_with_utf8_flipped ) ;
255
245
}
256
246
257
247
// Extra cost of having escapes in a block
@@ -265,39 +255,39 @@ struct feature_benchmarker {
265
255
// Rate of escape misses per escape flip
266
256
double escape_miss_rate (BenchmarkStage stage) const {
267
257
if (!has_events ()) { return 1 ; }
268
- return double (escape_miss[stage].best .branch_misses () - escape[stage].best .branch_misses ()) / escape_miss.stats ->blocks_with_escapes_flipped ;
258
+ return double (escape_miss[stage].best .branch_misses () - escape[stage].best .branch_misses ()) / double ( escape_miss.stats ->blocks_with_escapes_flipped ) ;
269
259
}
270
260
271
261
double calc_expected_feature_cost (BenchmarkStage stage, const benchmarker& file) const {
272
262
// Expected base ns/block (empty)
273
263
json_stats& stats = *file.stats ;
274
- double expected = base_cost (stage) * stats.blocks ;
275
- expected += struct1_7_cost (stage) * stats.blocks_with_1_structural ;
276
- expected += utf8_cost (stage) * stats.blocks_with_utf8 ;
277
- expected += escape_cost (stage) * stats.blocks_with_escapes ;
278
- expected += struct8_15_cost (stage) * stats.blocks_with_8_structurals ;
279
- expected += struct16_cost (stage) * stats.blocks_with_16_structurals ;
280
- return expected / stats.blocks ;
264
+ double expected = base_cost (stage) * double ( stats.blocks ) ;
265
+ expected += struct1_7_cost (stage) * double ( stats.blocks_with_1_structural ) ;
266
+ expected += utf8_cost (stage) * double ( stats.blocks_with_utf8 ) ;
267
+ expected += escape_cost (stage) * double ( stats.blocks_with_escapes ) ;
268
+ expected += struct8_15_cost (stage) * double ( stats.blocks_with_8_structurals ) ;
269
+ expected += struct16_cost (stage) * double ( stats.blocks_with_16_structurals ) ;
270
+ return expected / double ( stats.blocks ) ;
281
271
}
282
272
283
273
double calc_expected_miss_cost (BenchmarkStage stage, const benchmarker& file) const {
284
274
// Expected base ns/block (empty)
285
275
json_stats& stats = *file.stats ;
286
- double expected = struct1_7_miss_cost (stage) * stats.blocks_with_1_structural_flipped * struct1_7_miss_rate (stage);
287
- expected += utf8_miss_cost (stage) * stats.blocks_with_utf8_flipped * utf8_miss_rate (stage);
288
- expected += escape_miss_cost (stage) * stats.blocks_with_escapes_flipped * escape_miss_rate (stage);
289
- expected += struct8_15_miss_cost (stage) * stats.blocks_with_8_structurals_flipped * struct8_15_miss_rate (stage);
290
- expected += struct16_miss_cost (stage) * stats.blocks_with_16_structurals_flipped * struct16_miss_rate (stage);
291
- return expected / stats.blocks ;
276
+ double expected = struct1_7_miss_cost (stage) * double ( stats.blocks_with_1_structural_flipped ) * struct1_7_miss_rate (stage);
277
+ expected += utf8_miss_cost (stage) * double ( stats.blocks_with_utf8_flipped ) * utf8_miss_rate (stage);
278
+ expected += escape_miss_cost (stage) * double ( stats.blocks_with_escapes_flipped ) * escape_miss_rate (stage);
279
+ expected += struct8_15_miss_cost (stage) * double ( stats.blocks_with_8_structurals_flipped ) * struct8_15_miss_rate (stage);
280
+ expected += struct16_miss_cost (stage) * double ( stats.blocks_with_16_structurals_flipped ) * struct16_miss_rate (stage);
281
+ return expected / double ( stats.blocks ) ;
292
282
}
293
283
294
284
double calc_expected_misses (BenchmarkStage stage, const benchmarker& file) const {
295
285
json_stats& stats = *file.stats ;
296
- double expected = stats.blocks_with_1_structural_flipped * struct1_7_miss_rate (stage);
297
- expected += stats.blocks_with_utf8_flipped * utf8_miss_rate (stage);
298
- expected += stats.blocks_with_escapes_flipped * escape_miss_rate (stage);
299
- expected += stats.blocks_with_8_structurals_flipped * struct8_15_miss_rate (stage);
300
- expected += stats.blocks_with_16_structurals_flipped * struct16_miss_rate (stage);
286
+ double expected = double ( stats.blocks_with_1_structural_flipped ) * struct1_7_miss_rate (stage);
287
+ expected += double ( stats.blocks_with_utf8_flipped ) * utf8_miss_rate (stage);
288
+ expected += double ( stats.blocks_with_escapes_flipped ) * escape_miss_rate (stage);
289
+ expected += double ( stats.blocks_with_8_structurals_flipped ) * struct8_15_miss_rate (stage);
290
+ expected += double ( stats.blocks_with_16_structurals_flipped ) * struct16_miss_rate (stage);
301
291
return expected;
302
292
}
303
293
@@ -364,10 +354,10 @@ struct feature_benchmarker {
364
354
};
365
355
366
356
void print_file_effectiveness (BenchmarkStage stage, const char * filename, const benchmarker& results, const feature_benchmarker& features) {
367
- double actual = results[stage].best .elapsed_ns () / results.stats ->blocks ;
357
+ double actual = results[stage].best .elapsed_ns () / double ( results.stats ->blocks ) ;
368
358
double calc = features.calc_expected (stage, results);
369
- uint64_t actual_misses = results[stage].best .branch_misses ();
370
- uint64_t calc_misses = uint64_t ( features.calc_expected_misses (stage, results) );
359
+ double actual_misses = results[stage].best .branch_misses ();
360
+ double calc_misses = features.calc_expected_misses (stage, results);
371
361
double calc_miss_cost = features.calc_expected_miss_cost (stage, results);
372
362
printf (" | %-8s " , benchmark_stage_name (stage));
373
363
printf (" | %-15s " , filename);
@@ -376,10 +366,10 @@ void print_file_effectiveness(BenchmarkStage stage, const char* filename, const
376
366
printf (" | %8.3g " , calc);
377
367
printf (" | %8.3g " , actual);
378
368
printf (" | %+8.3g " , actual - calc);
379
- printf (" | %13lu " , calc_misses);
369
+ printf (" | %13llu " , ( long long unsigned )( calc_misses) );
380
370
if (features.has_events ()) {
381
- printf (" | %13lu " , actual_misses);
382
- printf (" | %+13ld " , int64_t (actual_misses - calc_misses));
371
+ printf (" | %13llu " , ( long long unsigned )( actual_misses) );
372
+ printf (" | %+13lld " , ( long long int ) (actual_misses - calc_misses));
383
373
double miss_adjustment = calc_miss_cost * (double (int64_t (actual_misses - calc_misses)) / calc_misses);
384
374
printf (" | %8.3g " , calc_miss_cost + miss_adjustment);
385
375
printf (" | %+8.3g " , actual - (calc + miss_adjustment));
@@ -401,9 +391,9 @@ int main(int argc, char *argv[]) {
401
391
402
392
// Set up benchmarkers by reading all files
403
393
feature_benchmarker features (collector);
404
- benchmarker gsoc_2018 (" jsonexamples/ gsoc-2018.json" , collector);
405
- benchmarker twitter (" jsonexamples/ twitter.json" , collector);
406
- benchmarker random (" jsonexamples/ random.json" , collector);
394
+ benchmarker gsoc_2018 (SIMDJSON_BENCHMARK_DATA_DIR " gsoc-2018.json" , collector);
395
+ benchmarker twitter (SIMDJSON_BENCHMARK_DATA_DIR " twitter.json" , collector);
396
+ benchmarker random (SIMDJSON_BENCHMARK_DATA_DIR " random.json" , collector);
407
397
408
398
// Run the benchmarks
409
399
progress_bar progress (options.iterations , 100 );
0 commit comments