benchmark/src/json_reporter.cc
Go to the documentation of this file.
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <cstdint>
18 #include <iomanip> // for setprecision
19 #include <iostream>
20 #include <limits>
21 #include <string>
22 #include <tuple>
23 #include <vector>
24 
25 #include "benchmark/benchmark.h"
26 #include "complexity.h"
27 #include "string_util.h"
28 #include "timers.h"
29 
30 namespace benchmark {
31 namespace internal {
32 extern std::map<std::string, std::string>* global_context;
33 }
34 
35 namespace {
36 
37 std::string StrEscape(const std::string& s) {
39  tmp.reserve(s.size());
40  for (char c : s) {
41  switch (c) {
42  case '\b':
43  tmp += "\\b";
44  break;
45  case '\f':
46  tmp += "\\f";
47  break;
48  case '\n':
49  tmp += "\\n";
50  break;
51  case '\r':
52  tmp += "\\r";
53  break;
54  case '\t':
55  tmp += "\\t";
56  break;
57  case '\\':
58  tmp += "\\\\";
59  break;
60  case '"':
61  tmp += "\\\"";
62  break;
63  default:
64  tmp += c;
65  break;
66  }
67  }
68  return tmp;
69 }
70 
71 std::string FormatKV(std::string const& key, std::string const& value) {
72  return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(),
73  StrEscape(value).c_str());
74 }
75 
76 std::string FormatKV(std::string const& key, const char* value) {
77  return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(),
78  StrEscape(value).c_str());
79 }
80 
81 std::string FormatKV(std::string const& key, bool value) {
82  return StrFormat("\"%s\": %s", StrEscape(key).c_str(),
83  value ? "true" : "false");
84 }
85 
86 std::string FormatKV(std::string const& key, int64_t value) {
87  std::stringstream ss;
88  ss << '"' << StrEscape(key) << "\": " << value;
89  return ss.str();
90 }
91 
93  std::stringstream ss;
94  ss << '"' << StrEscape(key) << "\": " << value;
95  return ss.str();
96 }
97 
98 std::string FormatKV(std::string const& key, double value) {
99  std::stringstream ss;
100  ss << '"' << StrEscape(key) << "\": ";
101 
102  if (std::isnan(value))
103  ss << (value < 0 ? "-" : "") << "NaN";
104  else if (std::isinf(value))
105  ss << (value < 0 ? "-" : "") << "Infinity";
106  else {
107  const auto max_digits10 =
108  std::numeric_limits<decltype(value)>::max_digits10;
109  const auto max_fractional_digits10 = max_digits10 - 1;
110  ss << std::scientific << std::setprecision(max_fractional_digits10)
111  << value;
112  }
113  return ss.str();
114 }
115 
116 int64_t RoundDouble(double v) { return std::lround(v); }
117 
118 } // end namespace
119 
121  std::ostream& out = GetOutputStream();
122 
123  out << "{\n";
124  std::string inner_indent(2, ' ');
125 
126  // Open context block and print context information.
127  out << inner_indent << "\"context\": {\n";
128  std::string indent(4, ' ');
129 
130  std::string walltime_value = LocalDateTimeString();
131  out << indent << FormatKV("date", walltime_value) << ",\n";
132 
133  out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
134 
136  out << indent << FormatKV("executable", Context::executable_name) << ",\n";
137  }
138 
139  CPUInfo const& info = context.cpu_info;
140  out << indent << FormatKV("num_cpus", static_cast<int64_t>(info.num_cpus))
141  << ",\n";
142  out << indent
143  << FormatKV("mhz_per_cpu",
144  RoundDouble(info.cycles_per_second / 1000000.0))
145  << ",\n";
146  if (CPUInfo::Scaling::UNKNOWN != info.scaling) {
147  out << indent
148  << FormatKV("cpu_scaling_enabled",
149  info.scaling == CPUInfo::Scaling::ENABLED ? true : false)
150  << ",\n";
151  }
152 
153  out << indent << "\"caches\": [\n";
154  indent = std::string(6, ' ');
155  std::string cache_indent(8, ' ');
156  for (size_t i = 0; i < info.caches.size(); ++i) {
157  auto& CI = info.caches[i];
158  out << indent << "{\n";
159  out << cache_indent << FormatKV("type", CI.type) << ",\n";
160  out << cache_indent << FormatKV("level", static_cast<int64_t>(CI.level))
161  << ",\n";
162  out << cache_indent << FormatKV("size", static_cast<int64_t>(CI.size))
163  << ",\n";
164  out << cache_indent
165  << FormatKV("num_sharing", static_cast<int64_t>(CI.num_sharing))
166  << "\n";
167  out << indent << "}";
168  if (i != info.caches.size() - 1) out << ",";
169  out << "\n";
170  }
171  indent = std::string(4, ' ');
172  out << indent << "],\n";
173  out << indent << "\"load_avg\": [";
174  for (auto it = info.load_avg.begin(); it != info.load_avg.end();) {
175  out << *it++;
176  if (it != info.load_avg.end()) out << ",";
177  }
178  out << "],\n";
179 
180 #if defined(NDEBUG)
181  const char build_type[] = "release";
182 #else
183  const char build_type[] = "debug";
184 #endif
185  out << indent << FormatKV("library_build_type", build_type);
186 
187  if (internal::global_context != nullptr) {
188  for (const auto& kv : *internal::global_context) {
189  out << ",\n";
190  out << indent << FormatKV(kv.first, kv.second);
191  }
192  }
193  out << "\n";
194 
195  // Close context block and open the list of benchmarks.
196  out << inner_indent << "},\n";
197  out << inner_indent << "\"benchmarks\": [\n";
198  return true;
199 }
200 
201 void JSONReporter::ReportRuns(std::vector<Run> const& reports) {
202  if (reports.empty()) {
203  return;
204  }
205  std::string indent(4, ' ');
206  std::ostream& out = GetOutputStream();
207  if (!first_report_) {
208  out << ",\n";
209  }
210  first_report_ = false;
211 
212  for (auto it = reports.begin(); it != reports.end(); ++it) {
213  out << indent << "{\n";
214  PrintRunData(*it);
215  out << indent << '}';
216  auto it_cp = it;
217  if (++it_cp != reports.end()) {
218  out << ",\n";
219  }
220  }
221 }
222 
224  // Close the list of benchmarks and the top level object.
225  GetOutputStream() << "\n ]\n}\n";
226 }
227 
229  std::string indent(6, ' ');
230  std::ostream& out = GetOutputStream();
231  out << indent << FormatKV("name", run.benchmark_name()) << ",\n";
232  out << indent << FormatKV("family_index", run.family_index) << ",\n";
233  out << indent
234  << FormatKV("per_family_instance_index", run.per_family_instance_index)
235  << ",\n";
236  out << indent << FormatKV("run_name", run.run_name.str()) << ",\n";
237  out << indent << FormatKV("run_type", [&run]() -> const char* {
238  switch (run.run_type) {
239  case BenchmarkReporter::Run::RT_Iteration:
240  return "iteration";
241  case BenchmarkReporter::Run::RT_Aggregate:
242  return "aggregate";
243  }
245  }()) << ",\n";
246  out << indent << FormatKV("repetitions", run.repetitions) << ",\n";
247  if (run.run_type != BenchmarkReporter::Run::RT_Aggregate) {
248  out << indent << FormatKV("repetition_index", run.repetition_index)
249  << ",\n";
250  }
251  out << indent << FormatKV("threads", run.threads) << ",\n";
252  if (run.run_type == BenchmarkReporter::Run::RT_Aggregate) {
253  out << indent << FormatKV("aggregate_name", run.aggregate_name) << ",\n";
254  out << indent << FormatKV("aggregate_unit", [&run]() -> const char* {
255  switch (run.aggregate_unit) {
256  case StatisticUnit::kTime:
257  return "time";
258  case StatisticUnit::kPercentage:
259  return "percentage";
260  }
262  }()) << ",\n";
263  }
264  if (run.error_occurred) {
265  out << indent << FormatKV("error_occurred", run.error_occurred) << ",\n";
266  out << indent << FormatKV("error_message", run.error_message) << ",\n";
267  }
268  if (!run.report_big_o && !run.report_rms) {
269  out << indent << FormatKV("iterations", run.iterations) << ",\n";
270  if (run.run_type != Run::RT_Aggregate ||
271  run.aggregate_unit == StatisticUnit::kTime) {
272  out << indent << FormatKV("real_time", run.GetAdjustedRealTime())
273  << ",\n";
274  out << indent << FormatKV("cpu_time", run.GetAdjustedCPUTime());
275  } else {
276  assert(run.aggregate_unit == StatisticUnit::kPercentage);
277  out << indent << FormatKV("real_time", run.real_accumulated_time)
278  << ",\n";
279  out << indent << FormatKV("cpu_time", run.cpu_accumulated_time);
280  }
281  out << ",\n"
282  << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
283  } else if (run.report_big_o) {
284  out << indent << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime())
285  << ",\n";
286  out << indent << FormatKV("real_coefficient", run.GetAdjustedRealTime())
287  << ",\n";
288  out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n";
289  out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
290  } else if (run.report_rms) {
291  out << indent << FormatKV("rms", run.GetAdjustedCPUTime());
292  }
293 
294  for (auto& c : run.counters) {
295  out << ",\n" << indent << FormatKV(c.first, c.second);
296  }
297 
298  if (run.has_memory_result) {
299  out << ",\n" << indent << FormatKV("allocs_per_iter", run.allocs_per_iter);
300  out << ",\n" << indent << FormatKV("max_bytes_used", run.max_bytes_used);
301  }
302 
303  if (!run.report_label.empty()) {
304  out << ",\n" << indent << FormatKV("label", run.report_label);
305  }
306  out << '\n';
307 }
308 
309 } // end namespace benchmark
benchmark::kTime
@ kTime
Definition: benchmark/include/benchmark/benchmark.h:453
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
benchmark::BenchmarkReporter::Run::RT_Aggregate
@ RT_Aggregate
Definition: benchmark/include/benchmark/benchmark.h:1425
regen-readme.it
it
Definition: regen-readme.py:15
benchmark::CPUInfo::load_avg
std::vector< double > load_avg
Definition: benchmark/include/benchmark/benchmark.h:1371
benchmark::JSONReporter::PrintRunData
void PrintRunData(const Run &report)
Definition: benchmark/src/json_reporter.cc:228
benchmark::kPercentage
@ kPercentage
Definition: benchmark/include/benchmark/benchmark.h:453
benchmark
Definition: bm_alarm.cc:55
fix_build_deps.c
list c
Definition: fix_build_deps.py:490
benchmark::CPUInfo::scaling
Scaling scaling
Definition: benchmark/include/benchmark/benchmark.h:1368
tests.google.protobuf.internal.message_test.isnan
def isnan(val)
Definition: bloaty/third_party/protobuf/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py:65
BENCHMARK_UNREACHABLE
#define BENCHMARK_UNREACHABLE()
Definition: benchmark/include/benchmark/benchmark.h:265
timers.h
benchmark::CPUInfo::cycles_per_second
double cycles_per_second
Definition: benchmark/include/benchmark/benchmark.h:1369
benchmark::JSONReporter::first_report_
bool first_report_
Definition: benchmark/include/benchmark/benchmark.h:1609
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
absl::FormatConversionChar::s
@ s
benchmark::BenchmarkReporter::Context::executable_name
static const char * executable_name
Definition: benchmark/include/benchmark/benchmark.h:1419
benchmark::JSONReporter::Finalize
virtual void Finalize() BENCHMARK_OVERRIDE
Definition: benchmark/src/json_reporter.cc:223
python_utils.upload_rbe_results.indent
indent
Definition: upload_rbe_results.py:183
benchmark::GetTimeUnitString
const char * GetTimeUnitString(TimeUnit unit)
Definition: benchmark/include/benchmark/benchmark.h:1650
benchmark::CPUInfo::num_cpus
int num_cpus
Definition: benchmark/include/benchmark/benchmark.h:1367
benchmark::JSONReporter::ReportContext
virtual bool ReportContext(const Context &context) BENCHMARK_OVERRIDE
Definition: benchmark/src/json_reporter.cc:120
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
gen_stats_data.c_str
def c_str(s, encoding='ascii')
Definition: gen_stats_data.py:38
benchmark::IterationCount
uint64_t IterationCount
Definition: benchmark/include/benchmark/benchmark.h:451
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
benchmark::BenchmarkReporter::Run
Definition: benchmark/include/benchmark/benchmark.h:1423
benchmark::JSONReporter::ReportRuns
virtual void ReportRuns(const std::vector< Run > &reports) BENCHMARK_OVERRIDE
Definition: benchmark/src/json_reporter.cc:201
benchmark::GetBigOString
std::string GetBigOString(BigO complexity)
Definition: benchmark/src/complexity.cc:53
value
const char * value
Definition: hpack_parser_table.cc:165
string_util.h
benchmark::StrFormat
std::string StrFormat(const char *format,...)
Definition: benchmark/src/string_util.cc:158
key
const char * key
Definition: hpack_parser_table.cc:164
client.run
def run()
Definition: examples/python/async_streaming/client.py:109
tests.google.protobuf.internal.message_test.isinf
def isinf(val)
Definition: bloaty/third_party/protobuf/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py:68
benchmark::internal::global_context
std::map< std::string, std::string > * global_context
Definition: benchmark/src/benchmark.cc:129
internal
Definition: benchmark/test/output_test_helper.cc:20
context
grpc::ClientContext context
Definition: istio_echo_server_lib.cc:61
benchmark::CPUInfo
Definition: benchmark/include/benchmark/benchmark.h:1353
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
complexity.h
benchmark::BenchmarkReporter::Context
Definition: benchmark/include/benchmark/benchmark.h:1414
benchmark::BenchmarkReporter::GetOutputStream
std::ostream & GetOutputStream() const
Definition: benchmark/include/benchmark/benchmark.h:1553
benchmark::LocalDateTimeString
std::string LocalDateTimeString()
Definition: benchmark/src/timers.cc:182
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
benchmark::CPUInfo::caches
std::vector< CacheInfo > caches
Definition: benchmark/include/benchmark/benchmark.h:1370


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:12