Home | History | Annotate | Download | only in src
      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/reporter.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 "string_util.h"
     26 #include "timers.h"
     27 #include "check.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 }
     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         user_counter_names_.insert(cnt.first);
     53       }
     54     }
     55 
     56     // print the header
     57     for (auto B = elements.begin(); B != elements.end();) {
     58       Out << *B++;
     59       if (B != elements.end()) Out << ",";
     60     }
     61     for (auto B = user_counter_names_.begin(); B != user_counter_names_.end();) {
     62       Out << ",\"" << *B++ << "\"";
     63     }
     64     Out << "\n";
     65 
     66     printed_header_ = true;
     67   } else {
     68     // check that all the current counters are saved in the name set
     69     for (const auto& run : reports) {
     70       for (const auto& cnt : run.counters) {
     71         CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end())
     72               << "All counters must be present in each run. "
     73               << "Counter named \"" << cnt.first
     74               << "\" was not in a run after being added to the header";
     75       }
     76     }
     77   }
     78 
     79   // print results for each run
     80   for (const auto& run : reports) {
     81     PrintRunData(run);
     82   }
     83 
     84 }
     85 
     86 void CSVReporter::PrintRunData(const Run & run) {
     87   std::ostream& Out = GetOutputStream();
     88 
     89   // Field with embedded double-quote characters must be doubled and the field
     90   // delimited with double-quotes.
     91   std::string name = run.benchmark_name;
     92   ReplaceAll(&name, "\"", "\"\"");
     93   Out << '"' << name << "\",";
     94   if (run.error_occurred) {
     95     Out << std::string(elements.size() - 3, ',');
     96     Out << "true,";
     97     std::string msg = run.error_message;
     98     ReplaceAll(&msg, "\"", "\"\"");
     99     Out << '"' << msg << "\"\n";
    100     return;
    101   }
    102 
    103   // Do not print iteration on bigO and RMS report
    104   if (!run.report_big_o && !run.report_rms) {
    105     Out << run.iterations;
    106   }
    107   Out << ",";
    108 
    109   Out << run.GetAdjustedRealTime() << ",";
    110   Out << run.GetAdjustedCPUTime() << ",";
    111 
    112   // Do not print timeLabel on bigO and RMS report
    113   if (run.report_big_o) {
    114     Out << GetBigOString(run.complexity);
    115   } else if (!run.report_rms) {
    116     Out << GetTimeUnitString(run.time_unit);
    117   }
    118   Out << ",";
    119 
    120   if (run.bytes_per_second > 0.0) {
    121     Out << run.bytes_per_second;
    122   }
    123   Out << ",";
    124   if (run.items_per_second > 0.0) {
    125     Out << run.items_per_second;
    126   }
    127   Out << ",";
    128   if (!run.report_label.empty()) {
    129     // Field with embedded double-quote characters must be doubled and the field
    130     // delimited with double-quotes.
    131     std::string label = run.report_label;
    132     ReplaceAll(&label, "\"", "\"\"");
    133     Out << "\"" << label << "\"";
    134   }
    135   Out << ",,";  // for error_occurred and error_message
    136 
    137   // Print user counters
    138   for (const auto &ucn : user_counter_names_) {
    139     auto it = run.counters.find(ucn);
    140     CHECK(it != run.counters.end());
    141     Out << "," << it->second;
    142   }
    143   Out << '\n';
    144 }
    145 
    146 }  // end namespace benchmark
    147