1 // Copyright 2015 Google Inc. All rights reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include "benchmark/benchmark.h"
24 #include "complexity.h"
25 #include "string_util.h"
28 // File format reference: http://edoceo.com/utilitas/csv-file-format.
33 std::vector
<std::string
> elements
= {
34 "name", "iterations", "real_time", "cpu_time",
35 "time_unit", "bytes_per_second", "items_per_second", "label",
36 "error_occurred", "error_message"};
39 std::string
CsvEscape(const std::string
& s
) {
41 tmp
.reserve(s
.size() + 2);
52 return '"' + tmp
+ '"';
56 bool CSVReporter::ReportContext(const Context
& context
) {
57 PrintBasicContext(&GetErrorStream(), context
);
62 void CSVReporter::ReportRuns(const std::vector
<Run
>& reports
) {
63 std::ostream
& Out
= GetOutputStream();
65 if (!printed_header_
) {
66 // save the names of all the user counters
67 for (const auto& run
: reports
) {
68 for (const auto& cnt
: run
.counters
) {
69 if (cnt
.first
== "bytes_per_second" || cnt
.first
== "items_per_second")
71 user_counter_names_
.insert(cnt
.first
);
76 for (auto B
= elements
.begin(); B
!= elements
.end();) {
78 if (B
!= elements
.end()) Out
<< ",";
80 for (auto B
= user_counter_names_
.begin();
81 B
!= user_counter_names_
.end();) {
82 Out
<< ",\"" << *B
++ << "\"";
86 printed_header_
= true;
88 // check that all the current counters are saved in the name set
89 for (const auto& run
: reports
) {
90 for (const auto& cnt
: run
.counters
) {
91 if (cnt
.first
== "bytes_per_second" || cnt
.first
== "items_per_second")
93 BM_CHECK(user_counter_names_
.find(cnt
.first
) !=
94 user_counter_names_
.end())
95 << "All counters must be present in each run. "
96 << "Counter named \"" << cnt
.first
97 << "\" was not in a run after being added to the header";
102 // print results for each run
103 for (const auto& run
: reports
) {
109 void CSVReporter::PrintRunData(const Run
& run
) {
110 std::ostream
& Out
= GetOutputStream();
111 Out
<< CsvEscape(run
.benchmark_name()) << ",";
113 Out
<< std::string(elements
.size() - 3, ',');
114 Out
<< std::boolalpha
<< (internal::SkippedWithError
== run
.skipped
) << ",";
115 Out
<< CsvEscape(run
.skip_message
) << "\n";
119 // Do not print iteration on bigO and RMS report
120 if (!run
.report_big_o
&& !run
.report_rms
) {
121 Out
<< run
.iterations
;
125 if (run
.run_type
!= Run::RT_Aggregate
||
126 run
.aggregate_unit
== StatisticUnit::kTime
) {
127 Out
<< run
.GetAdjustedRealTime() << ",";
128 Out
<< run
.GetAdjustedCPUTime() << ",";
130 assert(run
.aggregate_unit
== StatisticUnit::kPercentage
);
131 Out
<< run
.real_accumulated_time
<< ",";
132 Out
<< run
.cpu_accumulated_time
<< ",";
135 // Do not print timeLabel on bigO and RMS report
136 if (run
.report_big_o
) {
137 Out
<< GetBigOString(run
.complexity
);
138 } else if (!run
.report_rms
&&
139 run
.aggregate_unit
!= StatisticUnit::kPercentage
) {
140 Out
<< GetTimeUnitString(run
.time_unit
);
144 if (run
.counters
.find("bytes_per_second") != run
.counters
.end()) {
145 Out
<< run
.counters
.at("bytes_per_second");
148 if (run
.counters
.find("items_per_second") != run
.counters
.end()) {
149 Out
<< run
.counters
.at("items_per_second");
152 if (!run
.report_label
.empty()) {
153 Out
<< CsvEscape(run
.report_label
);
155 Out
<< ",,"; // for error_occurred and error_message
157 // Print user counters
158 for (const auto& ucn
: user_counter_names_
) {
159 auto it
= run
.counters
.find(ucn
);
160 if (it
== run
.counters
.end()) {
163 Out
<< "," << it
->second
;
169 } // end namespace benchmark