Skip to content

Commit f87e64f

Browse files
authored
Add option to make buffers hot and remove recent benchmarking changes (simdjson#443)
* This revert the code back to how it was prior to the silly "run two stages" routine and instead adds an option to benchmark the code over hot buffers. It turns out that it can be expensive, when the files are large, to allocate the pages.
1 parent 27861f6 commit f87e64f

File tree

2 files changed

+23
-31
lines changed

2 files changed

+23
-31
lines changed

benchmark/benchmarker.h

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,19 @@ struct benchmarker {
280280
return all_stages.iterations;
281281
}
282282

283-
really_inline void run_iteration(bool stage1_only, bool rerunbothstages) {
283+
really_inline void run_iteration(bool stage1_only, bool hotbuffers) {
284284
// Allocate ParsedJson
285285
collector.start();
286286
ParsedJson pj;
287287
bool allocok = pj.allocate_capacity(json.size());
288288
event_count allocate_count = collector.end();
289289
allocate_stage << allocate_count;
290+
if(hotbuffers) {
291+
int result = parser.parse((const uint8_t *)json.data(), json.size(), pj);
292+
if (result != simdjson::SUCCESS) {
293+
exit_error(string("Failed to parse ") + filename + string(":") + pj.get_error_message());
294+
}
295+
}
290296

291297
if (!allocok) {
292298
exit_error(string("Unable to allocate_stage ") + to_string(json.size()) + " bytes for the JSON result.");
@@ -316,21 +322,7 @@ struct benchmarker {
316322
}
317323
stage2_count = collector.end();
318324
stage2 << stage2_count;
319-
if(rerunbothstages) {
320-
// You would think that the entire processing is just stage 1 + stage 2, but
321-
// empirically, that's not true! Not even close to be true in some instances.
322-
event_count allstages_count;
323-
collector.start();
324-
result = parser.parse((const uint8_t *)json.data(), json.size(), pj);
325-
if (result != simdjson::SUCCESS) {
326-
exit_error(string("Failed to parse ") + filename + " during overall parsing " + pj.get_error_message());
327-
}
328-
allstages_count = collector.end();
329-
all_stages << allstages_count;
330-
} else {
331-
// we are optimistic
332-
all_stages << stage1_count + stage2_count;
333-
}
325+
all_stages << allocate_count + stage1_count + stage2_count;
334326
}
335327
// Calculate stats the first time we parse
336328
if (stats == NULL) {
@@ -344,9 +336,9 @@ struct benchmarker {
344336
}
345337
}
346338

347-
really_inline void run_iterations(size_t iterations, bool stage1_only, bool rerunbothstages) {
339+
really_inline void run_iterations(size_t iterations, bool stage1_only, bool hotbuffers) {
348340
for (size_t i = 0; i<iterations; i++) {
349-
run_iteration(stage1_only, rerunbothstages);
341+
run_iteration(stage1_only, hotbuffers);
350342
}
351343
}
352344

@@ -449,8 +441,11 @@ struct benchmarker {
449441
printf("\n");
450442
printf("All Stages\n");
451443
print_aggregate("| " , all_stages.best);
452-
// printf("|- Allocation\n");
453-
// print_aggregate("| ", allocate_stage.best);
444+
// frequently, allocation is a tiny fraction of the running time so we omit it
445+
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages.best.elapsed_sec()) {
446+
printf("|- Allocation\n");
447+
print_aggregate("| ", allocate_stage.best);
448+
}
454449
printf("|- Stage 1\n");
455450
print_aggregate("| ", stage1.best);
456451
printf("|- Stage 2\n");

benchmark/parse.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,10 @@ void print_usage(ostream& out) {
7070
out << "-s STAGE - Stop after the given stage." << endl;
7171
out << " -s stage1 - Stop after find_structural_bits." << endl;
7272
out << " -s all - Run all stages." << endl;
73-
out << " -s allfast - Run all stages." << endl;
73+
out << "-H - Make the buffers hot (reduce page allocation during parsing)" << endl;
7474

7575
out << "-a ARCH - Use the parser with the designated architecture (HASWELL, WESTMERE" << endl;
7676
out << " or ARM64). By default, detects best supported architecture." << endl;
77-
out << "-o - Estimate the overall speed as stage 1 + stage 2 instead of a rerun of both" << endl;
78-
7977
}
8078

8179
void exit_usage(string message) {
@@ -95,13 +93,13 @@ struct option_struct {
9593

9694
bool verbose = false;
9795
bool tabbed_output = false;
98-
bool rerunbothstages = true;
96+
bool hotbuffers = false;
9997

10098
option_struct(int argc, char **argv) {
10199
#ifndef _MSC_VER
102100
int c;
103101

104-
while ((c = getopt(argc, argv, "vtn:i:a:s:")) != -1) {
102+
while ((c = getopt(argc, argv, "vtn:i:a:s:H")) != -1) {
105103
switch (c) {
106104
case 'n':
107105
iterations = atoi(optarg);
@@ -121,15 +119,14 @@ struct option_struct {
121119
exit_usage(string("Unsupported option value -a ") + optarg + ": expected -a HASWELL, WESTMERE or ARM64");
122120
}
123121
break;
122+
case 'H':
123+
hotbuffers = true;
124+
break;
124125
case 's':
125126
if (!strcmp(optarg, "stage1")) {
126127
stage1_only = true;
127128
} else if (!strcmp(optarg, "all")) {
128129
stage1_only = false;
129-
rerunbothstages = true; // for safety
130-
} else if (!strcmp(optarg, "allfast")) {
131-
stage1_only = false;
132-
rerunbothstages = false;
133130
} else {
134131
exit_usage(string("Unsupported option value -s ") + optarg + ": expected -s stage1 or all");
135132
}
@@ -204,7 +201,7 @@ int main(int argc, char *argv[]) {
204201
// Benchmark each file once per iteration
205202
for (size_t f=0; f<options.files.size(); f++) {
206203
verbose() << "[verbose] " << benchmarkers[f]->filename << " iterations #" << iteration << "-" << (iteration+options.iteration_step-1) << endl;
207-
benchmarkers[f]->run_iterations(options.iteration_step, true, false);
204+
benchmarkers[f]->run_iterations(options.iteration_step, true, options.hotbuffers);
208205
}
209206
}
210207
} else {
@@ -213,7 +210,7 @@ int main(int argc, char *argv[]) {
213210
// Benchmark each file once per iteration
214211
for (size_t f=0; f<options.files.size(); f++) {
215212
verbose() << "[verbose] " << benchmarkers[f]->filename << " iterations #" << iteration << "-" << (iteration+options.iteration_step-1) << endl;
216-
benchmarkers[f]->run_iterations(options.iteration_step, false, options.rerunbothstages);
213+
benchmarkers[f]->run_iterations(options.iteration_step, false, options.hotbuffers);
217214
}
218215
}
219216
}

0 commit comments

Comments
 (0)