Commit efdc6894 authored by Adam Simpkins's avatar Adam Simpkins Committed by Tudor Bosman

folly: print nice time suffixes in benchmark output

Summary: Print the times using "ms" for milliseconds, "us" for microseconds, etc.

Test Plan:
$ ./_bin/folly/test/benchmark_test
======================================================================
folly/test/BenchmarkTest.cpp              relative  time/iter  iters/s
======================================================================
bmFun                                                  3.36ns  298.01M
bmRepeatedFun                                          1.76ns  569.38M
----------------------------------------------------------------------
gun                                                    1.70ns  589.82M
----------------------------------------------------------------------
baselinevector                                         3.08us  324.87K
bmVector                                    13.64%    22.56us   44.32K
----------------------------------------------------------------------
superslow                                               1.00s  999.82m
======================================================================

Reviewed By: andrei.alexandrescu@fb.com

FB internal diff: D546209
parent c14f40fc
...@@ -247,68 +247,69 @@ static double runBenchmarkGetNSPerIteration(const BenchmarkFun& fun, ...@@ -247,68 +247,69 @@ static double runBenchmarkGetNSPerIteration(const BenchmarkFun& fun,
return max(0.0, estimateTime(epochResults, epochResults + actualEpochs)); return max(0.0, estimateTime(epochResults, epochResults + actualEpochs));
} }
static string humanReadable(double n, unsigned int decimals) { struct ScaleInfo {
auto a = fabs(n); double boundary;
char suffix = ' '; const char* suffix;
};
if (a >= 1E21) {
// Too big to be comprehended by the puny human brain static const ScaleInfo kTimeSuffixes[] {
suffix = '!'; { 365.25 * 24 * 3600, "years" },
n /= 1E21; { 24 * 3600, "days" },
} else if (a >= 1E18) { { 3600, "hr" },
// "EXA" written with suffix 'X' so as to not create confusion { 60, "min" },
// with scientific notation. { 1, "s" },
suffix = 'X'; { 1E-3, "ms" },
n /= 1E18; { 1E-6, "us" },
} else if (a >= 1E15) { { 1E-9, "ns" },
// "PETA" { 1E-12, "ps" },
suffix = 'P'; { 1E-15, "fs" },
n /= 1E15; { 0, NULL },
} else if (a >= 1E12) { };
// "TERA"
suffix = 'T'; static const ScaleInfo kMetricSuffixes[] {
n /= 1E12; { 1E24, "Y" }, // yotta
} else if (a >= 1E9) { { 1E21, "Z" }, // zetta
// "GIGA" { 1E18, "X" }, // "exa" written with suffix 'X' so as to not create
suffix = 'G'; // confusion with scientific notation
n /= 1E9; { 1E15, "P" }, // peta
} else if (a >= 1E6) { { 1E12, "T" }, // terra
// "MEGA" { 1E9, "G" }, // giga
suffix = 'M'; { 1E6, "M" }, // mega
n /= 1E6; { 1E3, "K" }, // kilo
} else if (a >= 1E3) { { 1, "" },
// "KILO" { 1E-3, "m" }, // milli
suffix = 'K'; { 1E-6, "u" }, // micro
n /= 1E3; { 1E-9, "n" }, // nano
} else if (a == 0.0) { { 1E-12, "p" }, // pico
suffix = ' '; { 1E-15, "f" }, // femto
} else if (a < 1E-15) { { 1E-18, "a" }, // atto
// too small { 1E-21, "z" }, // zepto
suffix = '?'; { 1E-24, "y" }, // yocto
n *= 1E18; { 0, NULL },
} else if (a < 1E-12) { };
// "femto"
suffix = 'f'; static string humanReadable(double n, unsigned int decimals,
n *= 1E15; const ScaleInfo* scales) {
} else if (a < 1E-9) { if (std::isinf(n) || std::isnan(n)) {
// "pico" return folly::to<string>(n);
suffix = 'p';
n *= 1E12;
} else if (a < 1E-6) {
// "nano"
suffix = 'n';
n *= 1E9;
} else if (a < 1E-3) {
// "micro"
suffix = 'u';
n *= 1E6;
} else if (a < 1) {
// "mili"
suffix = 'm';
n *= 1E3;
} }
return stringPrintf("%*.*f%c", decimals + 3 + 1, decimals, n, suffix); const double absValue = fabs(n);
const ScaleInfo* scale = scales;
while (absValue < scale[0].boundary && scale[1].suffix != NULL) {
++scale;
}
const double scaledValue = n / scale->boundary;
return stringPrintf("%.*f%s", decimals, scaledValue, scale->suffix);
}
static string readableTime(double n, unsigned int decimals) {
return humanReadable(n, decimals, kTimeSuffixes);
}
static string metricReadable(double n, unsigned int decimals) {
return humanReadable(n, decimals, kMetricSuffixes);
} }
static void printBenchmarkResultsAsTable( static void printBenchmarkResultsAsTable(
...@@ -330,8 +331,8 @@ static void printBenchmarkResultsAsTable( ...@@ -330,8 +331,8 @@ static void printBenchmarkResultsAsTable(
// Print header for a file // Print header for a file
auto header = [&](const char* file) { auto header = [&](const char* file) {
separator('='); separator('=');
printf("%-*srelative ns/iter iters/s\n", printf("%-*srelative time/iter iters/s\n",
columns - 26, file); columns - 28, file);
separator('='); separator('=');
}; };
...@@ -359,23 +360,24 @@ static void printBenchmarkResultsAsTable( ...@@ -359,23 +360,24 @@ static void printBenchmarkResultsAsTable(
baselineNsPerIter = get<2>(datum); baselineNsPerIter = get<2>(datum);
useBaseline = false; useBaseline = false;
} }
s.resize(columns - 27, ' '); s.resize(columns - 29, ' ');
auto nsPerIter = get<2>(datum); auto nsPerIter = get<2>(datum);
auto itersPerSec = 1E9 / nsPerIter; auto secPerIter = nsPerIter / 1E9;
auto itersPerSec = 1 / secPerIter;
if (!useBaseline) { if (!useBaseline) {
// Print without baseline // Print without baseline
printf("%*s %s %s\n", printf("%*s %9s %7s\n",
static_cast<int>(s.size()), s.c_str(), static_cast<int>(s.size()), s.c_str(),
humanReadable(nsPerIter, 2).c_str(), readableTime(secPerIter, 2).c_str(),
humanReadable(itersPerSec, 2).c_str()); metricReadable(itersPerSec, 2).c_str());
} else { } else {
// Print with baseline // Print with baseline
auto rel = baselineNsPerIter / nsPerIter * 100.0; auto rel = baselineNsPerIter / nsPerIter * 100.0;
printf("%*s %7.2f%% %s %s\n", printf("%*s %7.2f%% %9s %7s\n",
static_cast<int>(s.size()), s.c_str(), static_cast<int>(s.size()), s.c_str(),
rel, rel,
humanReadable(nsPerIter, 2).c_str(), readableTime(secPerIter, 2).c_str(),
humanReadable(itersPerSec, 2).c_str()); metricReadable(itersPerSec, 2).c_str());
} }
} }
separator('='); separator('=');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment