csv_reporter.cc (4559B)
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 "benchmark/benchmark.h" 16 #include "complexity.h" 17 18 #include <algorithm> 19 #include <cstdint> 20 #include <iostream> 21 #include <string> 22 #include <tuple> 23 #include <vector> 24 25 #include "check.h" 26 #include "string_util.h" 27 #include "timers.h" 28 29 // File format reference: http://edoceo.com/utilitas/csv-file-format. 30 31 namespace benchmark { 32 33 namespace { 34 std::vector<std::string> elements = { 35 "name", "iterations", "real_time", "cpu_time", 36 "time_unit", "bytes_per_second", "items_per_second", "label", 37 "error_occurred", "error_message"}; 38 } // namespace 39 40 bool CSVReporter::ReportContext(const Context& context) { 41 PrintBasicContext(&GetErrorStream(), context); 42 return true; 43 } 44 45 void CSVReporter::ReportRuns(const std::vector<Run>& reports) { 46 std::ostream& Out = GetOutputStream(); 47 48 if (!printed_header_) { 49 // save the names of all the user counters 50 for (const auto& run : reports) { 51 for (const auto& cnt : run.counters) { 52 if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") 53 continue; 54 user_counter_names_.insert(cnt.first); 55 } 56 } 57 58 // print the header 59 for (auto B = elements.begin(); B != elements.end();) { 60 Out << *B++; 61 if (B != elements.end()) Out << ","; 62 } 63 for (auto B = user_counter_names_.begin(); 64 B != user_counter_names_.end();) { 65 Out << ",\"" << *B++ << "\""; 66 } 67 Out << "\n"; 68 69 printed_header_ = true; 70 } else { 71 // check that all the current counters are saved in the name set 72 for (const auto& run : reports) { 73 for (const auto& cnt : run.counters) { 74 if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") 75 continue; 76 CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end()) 77 << "All counters must be present in each run. " 78 << "Counter named \"" << cnt.first 79 << "\" was not in a run after being added to the header"; 80 } 81 } 82 } 83 84 // print results for each run 85 for (const auto& run : reports) { 86 PrintRunData(run); 87 } 88 } 89 90 void CSVReporter::PrintRunData(const Run& run) { 91 std::ostream& Out = GetOutputStream(); 92 93 // Field with embedded double-quote characters must be doubled and the field 94 // delimited with double-quotes. 95 std::string name = run.benchmark_name(); 96 ReplaceAll(&name, "\"", "\"\""); 97 Out << '"' << name << "\","; 98 if (run.error_occurred) { 99 Out << std::string(elements.size() - 3, ','); 100 Out << "true,"; 101 std::string msg = run.error_message; 102 ReplaceAll(&msg, "\"", "\"\""); 103 Out << '"' << msg << "\"\n"; 104 return; 105 } 106 107 // Do not print iteration on bigO and RMS report 108 if (!run.report_big_o && !run.report_rms) { 109 Out << run.iterations; 110 } 111 Out << ","; 112 113 Out << run.GetAdjustedRealTime() << ","; 114 Out << run.GetAdjustedCPUTime() << ","; 115 116 // Do not print timeLabel on bigO and RMS report 117 if (run.report_big_o) { 118 Out << GetBigOString(run.complexity); 119 } else if (!run.report_rms) { 120 Out << GetTimeUnitString(run.time_unit); 121 } 122 Out << ","; 123 124 if (run.counters.find("bytes_per_second") != run.counters.end()) { 125 Out << run.counters.at("bytes_per_second"); 126 } 127 Out << ","; 128 if (run.counters.find("items_per_second") != run.counters.end()) { 129 Out << run.counters.at("items_per_second"); 130 } 131 Out << ","; 132 if (!run.report_label.empty()) { 133 // Field with embedded double-quote characters must be doubled and the field 134 // delimited with double-quotes. 135 std::string label = run.report_label; 136 ReplaceAll(&label, "\"", "\"\""); 137 Out << "\"" << label << "\""; 138 } 139 Out << ",,"; // for error_occurred and error_message 140 141 // Print user counters 142 for (const auto& ucn : user_counter_names_) { 143 auto it = run.counters.find(ucn); 144 if (it == run.counters.end()) { 145 Out << ","; 146 } else { 147 Out << "," << it->second; 148 } 149 } 150 Out << '\n'; 151 } 152 153 } // end namespace benchmark