+void benchmarkResultsToDynamic(
+ const vector<detail::BenchmarkResult>& data,
+ dynamic& out) {
+ out = dynamic::array;
+ for (auto& datum : data) {
+ out.push_back(dynamic::array(datum.file, datum.name, datum.timeInNs));
+ }
+}
+
+void benchmarkResultsFromDynamic(
+ const dynamic& d,
+ vector<detail::BenchmarkResult>& results) {
+ for (auto& datum : d) {
+ results.push_back(
+ {datum[0].asString(), datum[1].asString(), datum[2].asDouble()});
+ }
+}
+
+static pair<StringPiece, StringPiece> resultKey(
+ const detail::BenchmarkResult& result) {
+ return pair<StringPiece, StringPiece>(result.file, result.name);
+}
+
+void printResultComparison(
+ const vector<detail::BenchmarkResult>& base,
+ const vector<detail::BenchmarkResult>& test) {
+ map<pair<StringPiece, StringPiece>, double> baselines;
+
+ for (auto& baseResult : base) {
+ baselines[resultKey(baseResult)] = baseResult.timeInNs;
+ }
+ //
+ // Width available
+ static const unsigned int columns = 76;
+
+ // Compute the longest benchmark name
+ size_t longestName = 0;
+ for (auto& datum : test) {
+ longestName = max(longestName, datum.name.size());
+ }
+
+ // Print a horizontal rule
+ auto separator = [&](char pad) { puts(string(columns, pad).c_str()); };
+
+ // Print header for a file
+ auto header = [&](const string& file) {
+ separator('=');
+ printf("%-*srelative time/iter iters/s\n", columns - 28, file.c_str());
+ separator('=');
+ };
+
+ string lastFile;
+
+ for (auto& datum : test) {
+ folly::Optional<double> baseline =
+ folly::get_optional(baselines, resultKey(datum));
+ auto file = datum.file;
+ if (file != lastFile) {
+ // New file starting
+ header(file);
+ lastFile = file;
+ }
+
+ string s = datum.name;
+ if (s == "-") {
+ separator('-');
+ continue;
+ }
+ if (s[0] == '%') {
+ s.erase(0, 1);
+ }
+ s.resize(columns - 29, ' ');
+ auto nsPerIter = datum.timeInNs;
+ auto secPerIter = nsPerIter / 1E9;
+ auto itersPerSec = (secPerIter == 0)
+ ? std::numeric_limits<double>::infinity()
+ : (1 / secPerIter);
+ if (!baseline) {
+ // Print without baseline
+ printf(
+ "%*s %9s %7s\n",
+ static_cast<int>(s.size()),
+ s.c_str(),
+ readableTime(secPerIter, 2).c_str(),
+ metricReadable(itersPerSec, 2).c_str());
+ } else {
+ // Print with baseline
+ auto rel = *baseline / nsPerIter * 100.0;
+ printf(
+ "%*s %7.2f%% %9s %7s\n",
+ static_cast<int>(s.size()),
+ s.c_str(),
+ rel,
+ readableTime(secPerIter, 2).c_str(),
+ metricReadable(itersPerSec, 2).c_str());
+ }
+ }
+ separator('=');
+}
+