1a8c51b3fSopenharmony_ci// Copyright 2015 Google Inc. All rights reserved. 2a8c51b3fSopenharmony_ci// 3a8c51b3fSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4a8c51b3fSopenharmony_ci// you may not use this file except in compliance with the License. 5a8c51b3fSopenharmony_ci// You may obtain a copy of the License at 6a8c51b3fSopenharmony_ci// 7a8c51b3fSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8a8c51b3fSopenharmony_ci// 9a8c51b3fSopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10a8c51b3fSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11a8c51b3fSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12a8c51b3fSopenharmony_ci// See the License for the specific language governing permissions and 13a8c51b3fSopenharmony_ci// limitations under the License. 14a8c51b3fSopenharmony_ci 15a8c51b3fSopenharmony_ci#include <algorithm> 16a8c51b3fSopenharmony_ci#include <cstdint> 17a8c51b3fSopenharmony_ci#include <iostream> 18a8c51b3fSopenharmony_ci#include <string> 19a8c51b3fSopenharmony_ci#include <tuple> 20a8c51b3fSopenharmony_ci#include <vector> 21a8c51b3fSopenharmony_ci 22a8c51b3fSopenharmony_ci#include "benchmark/benchmark.h" 23a8c51b3fSopenharmony_ci#include "check.h" 24a8c51b3fSopenharmony_ci#include "complexity.h" 25a8c51b3fSopenharmony_ci#include "string_util.h" 26a8c51b3fSopenharmony_ci#include "timers.h" 27a8c51b3fSopenharmony_ci 28a8c51b3fSopenharmony_ci// File format reference: http://edoceo.com/utilitas/csv-file-format. 29a8c51b3fSopenharmony_ci 30a8c51b3fSopenharmony_cinamespace benchmark { 31a8c51b3fSopenharmony_ci 32a8c51b3fSopenharmony_cinamespace { 33a8c51b3fSopenharmony_cistd::vector<std::string> elements = { 34a8c51b3fSopenharmony_ci "name", "iterations", "real_time", "cpu_time", 35a8c51b3fSopenharmony_ci "time_unit", "bytes_per_second", "items_per_second", "label", 36a8c51b3fSopenharmony_ci "error_occurred", "error_message"}; 37a8c51b3fSopenharmony_ci} // namespace 38a8c51b3fSopenharmony_ci 39a8c51b3fSopenharmony_cistd::string CsvEscape(const std::string& s) { 40a8c51b3fSopenharmony_ci std::string tmp; 41a8c51b3fSopenharmony_ci tmp.reserve(s.size() + 2); 42a8c51b3fSopenharmony_ci for (char c : s) { 43a8c51b3fSopenharmony_ci switch (c) { 44a8c51b3fSopenharmony_ci case '"': 45a8c51b3fSopenharmony_ci tmp += "\"\""; 46a8c51b3fSopenharmony_ci break; 47a8c51b3fSopenharmony_ci default: 48a8c51b3fSopenharmony_ci tmp += c; 49a8c51b3fSopenharmony_ci break; 50a8c51b3fSopenharmony_ci } 51a8c51b3fSopenharmony_ci } 52a8c51b3fSopenharmony_ci return '"' + tmp + '"'; 53a8c51b3fSopenharmony_ci} 54a8c51b3fSopenharmony_ci 55a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 56a8c51b3fSopenharmony_cibool CSVReporter::ReportContext(const Context& context) { 57a8c51b3fSopenharmony_ci PrintBasicContext(&GetErrorStream(), context); 58a8c51b3fSopenharmony_ci return true; 59a8c51b3fSopenharmony_ci} 60a8c51b3fSopenharmony_ci 61a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 62a8c51b3fSopenharmony_civoid CSVReporter::ReportRuns(const std::vector<Run>& reports) { 63a8c51b3fSopenharmony_ci std::ostream& Out = GetOutputStream(); 64a8c51b3fSopenharmony_ci 65a8c51b3fSopenharmony_ci if (!printed_header_) { 66a8c51b3fSopenharmony_ci // save the names of all the user counters 67a8c51b3fSopenharmony_ci for (const auto& run : reports) { 68a8c51b3fSopenharmony_ci for (const auto& cnt : run.counters) { 69a8c51b3fSopenharmony_ci if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") 70a8c51b3fSopenharmony_ci continue; 71a8c51b3fSopenharmony_ci user_counter_names_.insert(cnt.first); 72a8c51b3fSopenharmony_ci } 73a8c51b3fSopenharmony_ci } 74a8c51b3fSopenharmony_ci 75a8c51b3fSopenharmony_ci // print the header 76a8c51b3fSopenharmony_ci for (auto B = elements.begin(); B != elements.end();) { 77a8c51b3fSopenharmony_ci Out << *B++; 78a8c51b3fSopenharmony_ci if (B != elements.end()) Out << ","; 79a8c51b3fSopenharmony_ci } 80a8c51b3fSopenharmony_ci for (auto B = user_counter_names_.begin(); 81a8c51b3fSopenharmony_ci B != user_counter_names_.end();) { 82a8c51b3fSopenharmony_ci Out << ",\"" << *B++ << "\""; 83a8c51b3fSopenharmony_ci } 84a8c51b3fSopenharmony_ci Out << "\n"; 85a8c51b3fSopenharmony_ci 86a8c51b3fSopenharmony_ci printed_header_ = true; 87a8c51b3fSopenharmony_ci } else { 88a8c51b3fSopenharmony_ci // check that all the current counters are saved in the name set 89a8c51b3fSopenharmony_ci for (const auto& run : reports) { 90a8c51b3fSopenharmony_ci for (const auto& cnt : run.counters) { 91a8c51b3fSopenharmony_ci if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second") 92a8c51b3fSopenharmony_ci continue; 93a8c51b3fSopenharmony_ci BM_CHECK(user_counter_names_.find(cnt.first) != 94a8c51b3fSopenharmony_ci user_counter_names_.end()) 95a8c51b3fSopenharmony_ci << "All counters must be present in each run. " 96a8c51b3fSopenharmony_ci << "Counter named \"" << cnt.first 97a8c51b3fSopenharmony_ci << "\" was not in a run after being added to the header"; 98a8c51b3fSopenharmony_ci } 99a8c51b3fSopenharmony_ci } 100a8c51b3fSopenharmony_ci } 101a8c51b3fSopenharmony_ci 102a8c51b3fSopenharmony_ci // print results for each run 103a8c51b3fSopenharmony_ci for (const auto& run : reports) { 104a8c51b3fSopenharmony_ci PrintRunData(run); 105a8c51b3fSopenharmony_ci } 106a8c51b3fSopenharmony_ci} 107a8c51b3fSopenharmony_ci 108a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 109a8c51b3fSopenharmony_civoid CSVReporter::PrintRunData(const Run& run) { 110a8c51b3fSopenharmony_ci std::ostream& Out = GetOutputStream(); 111a8c51b3fSopenharmony_ci Out << CsvEscape(run.benchmark_name()) << ","; 112a8c51b3fSopenharmony_ci if (run.skipped) { 113a8c51b3fSopenharmony_ci Out << std::string(elements.size() - 3, ','); 114a8c51b3fSopenharmony_ci Out << std::boolalpha << (internal::SkippedWithError == run.skipped) << ","; 115a8c51b3fSopenharmony_ci Out << CsvEscape(run.skip_message) << "\n"; 116a8c51b3fSopenharmony_ci return; 117a8c51b3fSopenharmony_ci } 118a8c51b3fSopenharmony_ci 119a8c51b3fSopenharmony_ci // Do not print iteration on bigO and RMS report 120a8c51b3fSopenharmony_ci if (!run.report_big_o && !run.report_rms) { 121a8c51b3fSopenharmony_ci Out << run.iterations; 122a8c51b3fSopenharmony_ci } 123a8c51b3fSopenharmony_ci Out << ","; 124a8c51b3fSopenharmony_ci 125a8c51b3fSopenharmony_ci Out << run.GetAdjustedRealTime() << ","; 126a8c51b3fSopenharmony_ci Out << run.GetAdjustedCPUTime() << ","; 127a8c51b3fSopenharmony_ci 128a8c51b3fSopenharmony_ci // Do not print timeLabel on bigO and RMS report 129a8c51b3fSopenharmony_ci if (run.report_big_o) { 130a8c51b3fSopenharmony_ci Out << GetBigOString(run.complexity); 131a8c51b3fSopenharmony_ci } else if (!run.report_rms) { 132a8c51b3fSopenharmony_ci Out << GetTimeUnitString(run.time_unit); 133a8c51b3fSopenharmony_ci } 134a8c51b3fSopenharmony_ci Out << ","; 135a8c51b3fSopenharmony_ci 136a8c51b3fSopenharmony_ci if (run.counters.find("bytes_per_second") != run.counters.end()) { 137a8c51b3fSopenharmony_ci Out << run.counters.at("bytes_per_second"); 138a8c51b3fSopenharmony_ci } 139a8c51b3fSopenharmony_ci Out << ","; 140a8c51b3fSopenharmony_ci if (run.counters.find("items_per_second") != run.counters.end()) { 141a8c51b3fSopenharmony_ci Out << run.counters.at("items_per_second"); 142a8c51b3fSopenharmony_ci } 143a8c51b3fSopenharmony_ci Out << ","; 144a8c51b3fSopenharmony_ci if (!run.report_label.empty()) { 145a8c51b3fSopenharmony_ci Out << CsvEscape(run.report_label); 146a8c51b3fSopenharmony_ci } 147a8c51b3fSopenharmony_ci Out << ",,"; // for error_occurred and error_message 148a8c51b3fSopenharmony_ci 149a8c51b3fSopenharmony_ci // Print user counters 150a8c51b3fSopenharmony_ci for (const auto& ucn : user_counter_names_) { 151a8c51b3fSopenharmony_ci auto it = run.counters.find(ucn); 152a8c51b3fSopenharmony_ci if (it == run.counters.end()) { 153a8c51b3fSopenharmony_ci Out << ","; 154a8c51b3fSopenharmony_ci } else { 155a8c51b3fSopenharmony_ci Out << "," << it->second; 156a8c51b3fSopenharmony_ci } 157a8c51b3fSopenharmony_ci } 158a8c51b3fSopenharmony_ci Out << '\n'; 159a8c51b3fSopenharmony_ci} 160a8c51b3fSopenharmony_ci 161a8c51b3fSopenharmony_ci} // end namespace benchmark 162