forked from mloskot/json_benchmark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_benchmark.hpp
142 lines (124 loc) · 3.51 KB
/
json_benchmark.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
// Copyright (C) 2013 Mateusz Loskot <mateusz@loskot.net>
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy
// at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef MLOSKOT_JSON_BENCHMARK_HPP_INCLUDED
#define MLOSKOT_JSON_BENCHMARK_HPP_INCLUDED
#include <algorithm>
#include <cassert>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>
#include <utility>
#include "high_resolution_timer.hpp"
// Uncomment to print all tested JSON data to stdout
#ifndef JSON_BENCHMARK_DUMP_PARSED_JSON
//#define JSON_BENCHMARK_DUMP_PARSED_JSON
#endif
namespace jsonbench
{
//
// Default benchmark settings
//
std::size_t max_marks = 2; // 10;
std::size_t max_iterations = 1000;
//
// Routines handling test data files
//
typedef std::vector<std::string> jsons_t;
inline jsons_t load_json(std::string file)
{
typedef std::string::value_type char_t;
typedef std::istreambuf_iterator<char_t> iterator_t;
jsons_t v;
std::ifstream ifs(file);
v.push_back(std::string(iterator_t(ifs), (iterator_t())));
return v;
}
inline jsons_t load_jsons(std::string file)
{
jsons_t v;
std::ifstream ifs(file);
for (std::string line; std::getline(ifs, line); )
v.push_back(line);
return v;
}
// load single large JSON string
inline jsons_t get_large()
{
return load_json("data/canada.json");
}
// load collection of small to medium size JSON strings
inline jsons_t get_small()
{
return load_jsons("data/one-json-per-line.jsons");
}
//
// Benchmark running routines
//
typedef std::tuple<std::size_t, std::size_t, std::size_t, double, double> result_t;
template <typename Result>
inline std::ostream& print_result(std::ostream& os, Result r)
{
using std::get;
os << get<1>(r) << " iterations of " << get<2>(r) << " parsings in "
<< get<3>(r) << " to " << get<4>(r) << " sec based on "
<< get<0>(r) << " benchmarks" << std::endl;
return os;
}
template <typename Result, typename Timer>
inline void set_mark(Result& r, Timer const& t)
{
using std::get;
get<3>(r) = t.elapsed();
get<4>(r) = (std::max)(get<3>(r), get<4>(r));
get<3>(r) = (std::min)(get<3>(r), get<4>(r));
}
template <typename Container, typename Parse>
inline result_t benchmark(std::size_t marks, std::size_t iterations, Container const& jsons, Parse parse)
{
result_t r;
std::get<0>(r) = marks;
std::get<1>(r) = iterations;
std::get<2>(r) = jsons.size(); // batch size per iteration
for (decltype(marks) m = 0; m < marks; ++m)
{
util::high_resolution_timer t;
for (decltype(iterations) i = 0U; i < iterations; ++i)
{
for (auto const& s : jsons)
{
if (!parse(s))
throw std::runtime_error("parse failed");
}
}
set_mark(r, t);
}
return r;
}
template <typename Container, typename Parse>
inline result_t benchmark(Container const& jsons, Parse parse)
{
return benchmark(max_marks, max_iterations, jsons, parse);
}
template <typename Parse>
inline void run_benchmark(char const* name, Parse parse)
{
{
auto const marks = benchmark(max_marks, max_iterations, get_small(), parse);
print_result(std::cout << name << ".small: ", marks);
}
{
auto const marks = benchmark(max_marks, max_iterations, get_large(), parse);
print_result(std::cout << name << ".large: ", marks);
}
}
} // namespace jsonbench
#endif