Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force black and white output in google benchmark

Tags:

c++

xcode

cmake

I'm using google benchmark in Xcode and it's producing colored output for some reason. Since Xcode doesn't seem to support colored output I'm seeing undesired symbols. I was wondering if it is possible to force black and white output in google benchmark. I prefer answers that use their API but I'm open to other alternatives.

like image 814
German Capuano Avatar asked Sep 08 '17 12:09

German Capuano


1 Answers

Color output of Google Benchmark is mentioned in their Readme: https://github.com/google/benchmark#output-formats

Output Formats

The library supports multiple output formats. Use the --benchmark_format=<console|json|csv> flag to set the format type. console is the default format.

The Console format is intended to be a human readable format. By default the format generates color output. Context is output on stderr and the tabular data on stdout.

There is also option to save non-colored copy of output to file with --benchmark_out=file --benchmark_out_format=console (default is json)

The library supports writing the output of the benchmark to a file specified by --benchmark_out=<filename>. The format of the output can be specified using --benchmark_out_format={json|console|csv}. Specifying --benchmark_out does not suppress the console output.

And in implementation they have the flag to disable console coloring:

https://github.com/google/benchmark/blob/a271c36af93c7a3b19dfeb2aefa9ca77a58e52e4/src/benchmark.cc#L87

 DEFINE_string(benchmark_color, "auto",
          "Whether to use colors in the output.  Valid values: "
          "'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use "
          "colors if the output is being sent to a terminal and the TERM "
          "environment variable is set to a terminal type that supports "
          "colors.");

So, you can use --benchmark_color=false as suggested by Artemy (using wrapper shell script), or try to pass console output with "useless cat pattern":

 ./program | cat

It should set stdout to fail isatty() check in auto-color default mode (this trick works to disable color grep).

Or change your TERM env variable with export TERM=ansi to indicate that you have green-and-black CRT monitor: https://github.com/google/benchmark/blob/09b93ccc6a9aed84c269b6f5b8130c878e518ebb/src/colorprint.cc#L167

  //                 ... This list of
  // supported TERM values is copied from Google Test:
  // <https://github.com/google/googletest/blob/master/googletest/src/gtest.cc#L2925>.
  const char* const SUPPORTED_TERM_VALUES[] = {
      "xterm",         "xterm-color",     "xterm-256color",
      "screen",        "screen-256color", "tmux",
      "tmux-256color", "rxvt-unicode",    "rxvt-unicode-256color",
      "linux",         "cygwin",
};

But with |cat and export TERM=ansi gbench continues to generate color. It must be a bug (!!!) near GetOutputOptions, making IsColorTerminal() logic a noop in case of "auto", so "auto" mode is not really auto it is always enable:

ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
  int output_opts = ConsoleReporter::OO_Defaults;
  if ((FLAGS_benchmark_color == "auto" && IsColorTerminal()) ||
      IsTruthyFlagValue(FLAGS_benchmark_color)) {
    output_opts |= ConsoleReporter::OO_Color;
  } else {
    output_opts &= ~ConsoleReporter::OO_Color;
}

The IsTruthyFlagValue considers default value "auto" as true, and always enables color output, even when terminal does not support it!

bool IsTruthyFlagValue(const std::string& value) {
  if (value.empty()) return true;
  char ch = value[0];
  return isalnum(ch) &&
         !(ch == '0' || ch == 'f' || ch == 'F' || ch == 'n' || ch == 'N');
}   

Here is the patch to enable auto mode (will work with |cat and TERM=ansi ./program and probably with some IDEs which correctly sets TERM), fell free to do pull request:

--- a/src/benchmark.cc
+++ b/src/benchmark.cc
@@ -555,7 +555,8 @@ bool IsZero(double n) {
 ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
   int output_opts = ConsoleReporter::OO_Defaults;
   if ((FLAGS_benchmark_color == "auto" && IsColorTerminal()) ||
-      IsTruthyFlagValue(FLAGS_benchmark_color)) {
+      (FLAGS_benchmark_color != "auto" &&
+       IsTruthyFlagValue(FLAGS_benchmark_color))) {
     output_opts |= ConsoleReporter::OO_Color;
   } else {
     output_opts &= ~ConsoleReporter::OO_Color;
like image 107
osgx Avatar answered Oct 26 '22 00:10

osgx