Skip to content

Commit 2011c8b

Browse files
author
Fabien Coelho
committed
add loop option
1 parent ca0e41f commit 2011c8b

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

src/command_validate.cc

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,26 @@
1010
#include <iostream> // std::cerr
1111
#include <set> // std::set
1212
#include <string> // std::string
13+
#include <cmath> // for sqrt
1314

1415
#include "command.h"
1516
#include "utils.h"
1617

18+
// parse unsigned int option, how many loop for benchmarking
19+
auto benchmark_loop(
20+
const std::map<std::string, std::vector<std::string>> &options)
21+
-> size_t {
22+
23+
size_t loop = 1;
24+
25+
if (options.contains("loop")) {
26+
std::stringstream sstream(options.at("loop").front());
27+
sstream >> loop;
28+
}
29+
30+
return loop;
31+
}
32+
1733
// TODO: Add a flag to emit output using the standard JSON Schema output format
1834
// TODO: Add a flag to collect annotations
1935
// TODO: Add a flag to take a pre-compiled schema as input
@@ -56,6 +72,7 @@ auto sourcemeta::jsonschema::cli::validate(
5672

5773
const auto fast_mode{options.contains("f") || options.contains("fast")};
5874
const auto benchmark{options.contains("b") || options.contains("benchmark")};
75+
const auto bench_loop{benchmark_loop(options)};
5976
const auto trace{options.contains("t") || options.contains("trace")};
6077

6178
const sourcemeta::core::JSON bundled{
@@ -103,6 +120,7 @@ auto sourcemeta::jsonschema::cli::validate(
103120
const auto duration_us{
104121
std::chrono::duration_cast<std::chrono::microseconds>(
105122
timestamp_end - timestamp_start)};
123+
106124
if (subresult) {
107125
std::cout << "took: " << duration_us.count() << "us\n";
108126
} else {
@@ -158,15 +176,43 @@ auto sourcemeta::jsonschema::cli::validate(
158176
sourcemeta::core::empty_weak_pointer, frame};
159177
bool subresult{true};
160178
if (benchmark) {
161-
const auto timestamp_start{std::chrono::high_resolution_clock::now()};
162-
subresult = evaluator.validate(schema_template, instance);
163-
const auto timestamp_end{std::chrono::high_resolution_clock::now()};
164-
const auto duration_us{
165-
std::chrono::duration_cast<std::chrono::microseconds>(
166-
timestamp_end - timestamp_start)};
167-
if (subresult) {
168-
std::cout << "took: " << duration_us.count() << "us\n";
169-
} else {
179+
double sum = 0.0, sum2 = 0.0, empty = 0.0;
180+
size_t count = 0;
181+
182+
// overhead evaluation, if the compiler is kind enough not to optimize this out!
183+
for (auto i = bench_loop; i; i--) {
184+
const auto start{std::chrono::high_resolution_clock::now()};
185+
count++;
186+
const auto end{std::chrono::high_resolution_clock::now()};
187+
empty += (double)
188+
(std::chrono::duration_cast<std::chrono::microseconds>(end - start)).count();
189+
}
190+
assert(count == bench_loop);
191+
empty /= (double) bench_loop;
192+
193+
// execution time evaluation
194+
for (auto i = bench_loop; i; i--) {
195+
const auto start{std::chrono::high_resolution_clock::now()};
196+
197+
// force fast evaluation
198+
subresult = evaluator.validate(schema_template, instance);
199+
200+
const auto end{std::chrono::high_resolution_clock::now()};
201+
const auto delay = (double) (std::chrono::duration_cast<
202+
std::chrono::microseconds>(end - start)).count() - empty;
203+
204+
sum += delay;
205+
sum2 += delay * delay;
206+
}
207+
208+
// compute and show average execution time and standard deviation
209+
auto avg = sum / (double) bench_loop;
210+
auto stdev = sqrt(sum2 / (double) bench_loop - avg * avg);
211+
std::cout << std::fixed;
212+
std::cout.precision(3);
213+
std::cout << "took: " << avg << " +- " << stdev << " us (" << empty << ")\n";
214+
215+
if (!subresult) {
170216
error << "error: Schema validation failure\n";
171217
result = false;
172218
}

src/main.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ Global Options:
3535
validate <schema.json|.yaml> <instance.json|.jsonl|.yaml...> [--http/-h]
3636
[--benchmark/-b] [--extension/-e <extension>]
3737
[--ignore/-i <schemas-or-directories>] [--trace/-t] [--fast/-f]
38+
[--loop <iterations>]
3839
3940
Validate one or more instances against the given schema.
4041
4142
By default, schemas are validated in exhaustive mode, which results in
4243
better error messages, at the expense of speed. The --fast/-f option
4344
makes the schema compiler optimise for speed, at the expense of error
44-
messages.
45+
messages. Looping in benchmark mode allows to collect the execution time
46+
average and standard deviation for the fast mode on basic JSON data.
4547
4648
metaschema [schemas-or-directories...] [--http/-h]
4749
[--extension/-e <extension>]

0 commit comments

Comments
 (0)