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 <cstdio> 18a8c51b3fSopenharmony_ci#include <cstring> 19a8c51b3fSopenharmony_ci#include <iostream> 20a8c51b3fSopenharmony_ci#include <string> 21a8c51b3fSopenharmony_ci#include <tuple> 22a8c51b3fSopenharmony_ci#include <vector> 23a8c51b3fSopenharmony_ci 24a8c51b3fSopenharmony_ci#include "benchmark/benchmark.h" 25a8c51b3fSopenharmony_ci#include "check.h" 26a8c51b3fSopenharmony_ci#include "colorprint.h" 27a8c51b3fSopenharmony_ci#include "commandlineflags.h" 28a8c51b3fSopenharmony_ci#include "complexity.h" 29a8c51b3fSopenharmony_ci#include "counter.h" 30a8c51b3fSopenharmony_ci#include "internal_macros.h" 31a8c51b3fSopenharmony_ci#include "string_util.h" 32a8c51b3fSopenharmony_ci#include "timers.h" 33a8c51b3fSopenharmony_ci 34a8c51b3fSopenharmony_cinamespace benchmark { 35a8c51b3fSopenharmony_ci 36a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 37a8c51b3fSopenharmony_cibool ConsoleReporter::ReportContext(const Context& context) { 38a8c51b3fSopenharmony_ci name_field_width_ = context.name_field_width; 39a8c51b3fSopenharmony_ci printed_header_ = false; 40a8c51b3fSopenharmony_ci prev_counters_.clear(); 41a8c51b3fSopenharmony_ci 42a8c51b3fSopenharmony_ci PrintBasicContext(&GetErrorStream(), context); 43a8c51b3fSopenharmony_ci 44a8c51b3fSopenharmony_ci#ifdef BENCHMARK_OS_WINDOWS 45a8c51b3fSopenharmony_ci if ((output_options_ & OO_Color) && &std::cout != &GetOutputStream()) { 46a8c51b3fSopenharmony_ci GetErrorStream() 47a8c51b3fSopenharmony_ci << "Color printing is only supported for stdout on windows." 48a8c51b3fSopenharmony_ci " Disabling color printing\n"; 49a8c51b3fSopenharmony_ci output_options_ = static_cast<OutputOptions>(output_options_ & ~OO_Color); 50a8c51b3fSopenharmony_ci } 51a8c51b3fSopenharmony_ci#endif 52a8c51b3fSopenharmony_ci 53a8c51b3fSopenharmony_ci return true; 54a8c51b3fSopenharmony_ci} 55a8c51b3fSopenharmony_ci 56a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 57a8c51b3fSopenharmony_civoid ConsoleReporter::PrintHeader(const Run& run) { 58a8c51b3fSopenharmony_ci std::string str = 59a8c51b3fSopenharmony_ci FormatString("%-*s %13s %15s %12s", static_cast<int>(name_field_width_), 60a8c51b3fSopenharmony_ci "Benchmark", "Time", "CPU", "Iterations"); 61a8c51b3fSopenharmony_ci if (!run.counters.empty()) { 62a8c51b3fSopenharmony_ci if (output_options_ & OO_Tabular) { 63a8c51b3fSopenharmony_ci for (auto const& c : run.counters) { 64a8c51b3fSopenharmony_ci str += FormatString(" %10s", c.first.c_str()); 65a8c51b3fSopenharmony_ci } 66a8c51b3fSopenharmony_ci } else { 67a8c51b3fSopenharmony_ci str += " UserCounters..."; 68a8c51b3fSopenharmony_ci } 69a8c51b3fSopenharmony_ci } 70a8c51b3fSopenharmony_ci std::string line = std::string(str.length(), '-'); 71a8c51b3fSopenharmony_ci GetOutputStream() << line << "\n" << str << "\n" << line << "\n"; 72a8c51b3fSopenharmony_ci} 73a8c51b3fSopenharmony_ci 74a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 75a8c51b3fSopenharmony_civoid ConsoleReporter::ReportRuns(const std::vector<Run>& reports) { 76a8c51b3fSopenharmony_ci for (const auto& run : reports) { 77a8c51b3fSopenharmony_ci // print the header: 78a8c51b3fSopenharmony_ci // --- if none was printed yet 79a8c51b3fSopenharmony_ci bool print_header = !printed_header_; 80a8c51b3fSopenharmony_ci // --- or if the format is tabular and this run 81a8c51b3fSopenharmony_ci // has different fields from the prev header 82a8c51b3fSopenharmony_ci print_header |= (output_options_ & OO_Tabular) && 83a8c51b3fSopenharmony_ci (!internal::SameNames(run.counters, prev_counters_)); 84a8c51b3fSopenharmony_ci if (print_header) { 85a8c51b3fSopenharmony_ci printed_header_ = true; 86a8c51b3fSopenharmony_ci prev_counters_ = run.counters; 87a8c51b3fSopenharmony_ci PrintHeader(run); 88a8c51b3fSopenharmony_ci } 89a8c51b3fSopenharmony_ci // As an alternative to printing the headers like this, we could sort 90a8c51b3fSopenharmony_ci // the benchmarks by header and then print. But this would require 91a8c51b3fSopenharmony_ci // waiting for the full results before printing, or printing twice. 92a8c51b3fSopenharmony_ci PrintRunData(run); 93a8c51b3fSopenharmony_ci } 94a8c51b3fSopenharmony_ci} 95a8c51b3fSopenharmony_ci 96a8c51b3fSopenharmony_cistatic void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt, 97a8c51b3fSopenharmony_ci ...) { 98a8c51b3fSopenharmony_ci va_list args; 99a8c51b3fSopenharmony_ci va_start(args, fmt); 100a8c51b3fSopenharmony_ci out << FormatString(fmt, args); 101a8c51b3fSopenharmony_ci va_end(args); 102a8c51b3fSopenharmony_ci} 103a8c51b3fSopenharmony_ci 104a8c51b3fSopenharmony_cistatic std::string FormatTime(double time) { 105a8c51b3fSopenharmony_ci // For the time columns of the console printer 13 digits are reserved. One of 106a8c51b3fSopenharmony_ci // them is a space and max two of them are the time unit (e.g ns). That puts 107a8c51b3fSopenharmony_ci // us at 10 digits usable for the number. 108a8c51b3fSopenharmony_ci // Align decimal places... 109a8c51b3fSopenharmony_ci if (time < 1.0) { 110a8c51b3fSopenharmony_ci return FormatString("%10.3f", time); 111a8c51b3fSopenharmony_ci } 112a8c51b3fSopenharmony_ci if (time < 10.0) { 113a8c51b3fSopenharmony_ci return FormatString("%10.2f", time); 114a8c51b3fSopenharmony_ci } 115a8c51b3fSopenharmony_ci if (time < 100.0) { 116a8c51b3fSopenharmony_ci return FormatString("%10.1f", time); 117a8c51b3fSopenharmony_ci } 118a8c51b3fSopenharmony_ci // Assuming the time is at max 9.9999e+99 and we have 10 digits for the 119a8c51b3fSopenharmony_ci // number, we get 10-1(.)-1(e)-1(sign)-2(exponent) = 5 digits to print. 120a8c51b3fSopenharmony_ci if (time > 9999999999 /*max 10 digit number*/) { 121a8c51b3fSopenharmony_ci return FormatString("%1.4e", time); 122a8c51b3fSopenharmony_ci } 123a8c51b3fSopenharmony_ci return FormatString("%10.0f", time); 124a8c51b3fSopenharmony_ci} 125a8c51b3fSopenharmony_ci 126a8c51b3fSopenharmony_ciBENCHMARK_EXPORT 127a8c51b3fSopenharmony_civoid ConsoleReporter::PrintRunData(const Run& result) { 128a8c51b3fSopenharmony_ci typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...); 129a8c51b3fSopenharmony_ci auto& Out = GetOutputStream(); 130a8c51b3fSopenharmony_ci PrinterFn* printer = (output_options_ & OO_Color) 131a8c51b3fSopenharmony_ci ? static_cast<PrinterFn*>(ColorPrintf) 132a8c51b3fSopenharmony_ci : IgnoreColorPrint; 133a8c51b3fSopenharmony_ci auto name_color = 134a8c51b3fSopenharmony_ci (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN; 135a8c51b3fSopenharmony_ci printer(Out, name_color, "%-*s ", name_field_width_, 136a8c51b3fSopenharmony_ci result.benchmark_name().c_str()); 137a8c51b3fSopenharmony_ci 138a8c51b3fSopenharmony_ci if (internal::SkippedWithError == result.skipped) { 139a8c51b3fSopenharmony_ci printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'", 140a8c51b3fSopenharmony_ci result.skip_message.c_str()); 141a8c51b3fSopenharmony_ci printer(Out, COLOR_DEFAULT, "\n"); 142a8c51b3fSopenharmony_ci return; 143a8c51b3fSopenharmony_ci } else if (internal::SkippedWithMessage == result.skipped) { 144a8c51b3fSopenharmony_ci printer(Out, COLOR_WHITE, "SKIPPED: \'%s\'", result.skip_message.c_str()); 145a8c51b3fSopenharmony_ci printer(Out, COLOR_DEFAULT, "\n"); 146a8c51b3fSopenharmony_ci return; 147a8c51b3fSopenharmony_ci } 148a8c51b3fSopenharmony_ci 149a8c51b3fSopenharmony_ci const double real_time = result.GetAdjustedRealTime(); 150a8c51b3fSopenharmony_ci const double cpu_time = result.GetAdjustedCPUTime(); 151a8c51b3fSopenharmony_ci const std::string real_time_str = FormatTime(real_time); 152a8c51b3fSopenharmony_ci const std::string cpu_time_str = FormatTime(cpu_time); 153a8c51b3fSopenharmony_ci 154a8c51b3fSopenharmony_ci if (result.report_big_o) { 155a8c51b3fSopenharmony_ci std::string big_o = GetBigOString(result.complexity); 156a8c51b3fSopenharmony_ci printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time, 157a8c51b3fSopenharmony_ci big_o.c_str(), cpu_time, big_o.c_str()); 158a8c51b3fSopenharmony_ci } else if (result.report_rms) { 159a8c51b3fSopenharmony_ci printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%", 160a8c51b3fSopenharmony_ci cpu_time * 100, "%"); 161a8c51b3fSopenharmony_ci } else if (result.run_type != Run::RT_Aggregate || 162a8c51b3fSopenharmony_ci result.aggregate_unit == StatisticUnit::kTime) { 163a8c51b3fSopenharmony_ci const char* timeLabel = GetTimeUnitString(result.time_unit); 164a8c51b3fSopenharmony_ci printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(), 165a8c51b3fSopenharmony_ci timeLabel, cpu_time_str.c_str(), timeLabel); 166a8c51b3fSopenharmony_ci } else { 167a8c51b3fSopenharmony_ci assert(result.aggregate_unit == StatisticUnit::kPercentage); 168a8c51b3fSopenharmony_ci printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", 169a8c51b3fSopenharmony_ci (100. * result.real_accumulated_time), "%", 170a8c51b3fSopenharmony_ci (100. * result.cpu_accumulated_time), "%"); 171a8c51b3fSopenharmony_ci } 172a8c51b3fSopenharmony_ci 173a8c51b3fSopenharmony_ci if (!result.report_big_o && !result.report_rms) { 174a8c51b3fSopenharmony_ci printer(Out, COLOR_CYAN, "%10lld", result.iterations); 175a8c51b3fSopenharmony_ci } 176a8c51b3fSopenharmony_ci 177a8c51b3fSopenharmony_ci for (auto& c : result.counters) { 178a8c51b3fSopenharmony_ci const std::size_t cNameLen = 179a8c51b3fSopenharmony_ci std::max(std::string::size_type(10), c.first.length()); 180a8c51b3fSopenharmony_ci std::string s; 181a8c51b3fSopenharmony_ci const char* unit = ""; 182a8c51b3fSopenharmony_ci if (result.run_type == Run::RT_Aggregate && 183a8c51b3fSopenharmony_ci result.aggregate_unit == StatisticUnit::kPercentage) { 184a8c51b3fSopenharmony_ci s = StrFormat("%.2f", 100. * c.second.value); 185a8c51b3fSopenharmony_ci unit = "%"; 186a8c51b3fSopenharmony_ci } else { 187a8c51b3fSopenharmony_ci s = HumanReadableNumber(c.second.value, c.second.oneK); 188a8c51b3fSopenharmony_ci if (c.second.flags & Counter::kIsRate) 189a8c51b3fSopenharmony_ci unit = (c.second.flags & Counter::kInvert) ? "s" : "/s"; 190a8c51b3fSopenharmony_ci } 191a8c51b3fSopenharmony_ci if (output_options_ & OO_Tabular) { 192a8c51b3fSopenharmony_ci printer(Out, COLOR_DEFAULT, " %*s%s", cNameLen - strlen(unit), s.c_str(), 193a8c51b3fSopenharmony_ci unit); 194a8c51b3fSopenharmony_ci } else { 195a8c51b3fSopenharmony_ci printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), unit); 196a8c51b3fSopenharmony_ci } 197a8c51b3fSopenharmony_ci } 198a8c51b3fSopenharmony_ci 199a8c51b3fSopenharmony_ci if (!result.report_label.empty()) { 200a8c51b3fSopenharmony_ci printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str()); 201a8c51b3fSopenharmony_ci } 202a8c51b3fSopenharmony_ci 203a8c51b3fSopenharmony_ci printer(Out, COLOR_DEFAULT, "\n"); 204a8c51b3fSopenharmony_ci} 205a8c51b3fSopenharmony_ci 206a8c51b3fSopenharmony_ci} // end namespace benchmark 207