hacking on a single-benchmark tool

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2012413004

Review-Url: https://codereview.chromium.org/2012413004
diff --git a/tools/monobench.cpp b/tools/monobench.cpp
new file mode 100644
index 0000000..757e9d3
--- /dev/null
+++ b/tools/monobench.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Benchmark.h"
+#include "SkGraphics.h"
+#include <algorithm>
+#include <chrono>
+#include <regex>
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+int main(int argc, char** argv) {
+    SkGraphics::Init();
+
+    using clock = std::chrono::high_resolution_clock;
+    using ns = std::chrono::duration<double, std::nano>;
+
+    std::regex pattern;
+    if (argc > 1) {
+        pattern = argv[1];
+    }
+
+    struct Bench {
+        std::unique_ptr<Benchmark> b;
+        std::string                name;
+        ns                         best;
+    };
+    std::vector<Bench> benches;
+
+    for (auto r = BenchRegistry::Head(); r; r = r->next()) {
+        std::unique_ptr<Benchmark> bench{ r->factory()(nullptr) };
+
+        std::string name = bench->getName();
+        if (std::regex_search(name, pattern) &&
+                bench->isSuitableFor(Benchmark::kNonRendering_Backend)) {
+            bench->delayedSetup();
+            benches.emplace_back(Bench{std::move(bench), name, ns{1.0/0.0}});
+        }
+    }
+
+    if (benches.size() > 1) {
+        int common_prefix = benches[0].name.size();
+        for (size_t i = 1; i < benches.size(); i++) {
+            int len = std::mismatch(benches[i-1].name.begin(), benches[i-1].name.end(),
+                                    benches[i-0].name.begin())
+                .first - benches[i-1].name.begin();
+            common_prefix = std::min(common_prefix, len);
+        }
+        std::string prefix = benches[0].name.substr(0, common_prefix);
+        if (common_prefix) {
+            for (auto& bench : benches) {
+                bench.name.replace(0, common_prefix, "…");
+            }
+        }
+
+        int common_suffix = benches[0].name.size();
+        for (size_t i = 1; i < benches.size(); i++) {
+            int len = std::mismatch(benches[i-1].name.rbegin(), benches[i-1].name.rend(),
+                                    benches[i-0].name.rbegin())
+                .first - benches[i-1].name.rbegin();
+            common_suffix = std::min(common_suffix, len);
+        }
+        std::string suffix = benches[0].name.substr(benches[0].name.size() - common_suffix);
+        if (common_suffix) {
+            for (auto& bench : benches) {
+                bench.name.replace(bench.name.size() - common_suffix, common_suffix, "…");
+            }
+        }
+
+        printf("%s…%s\n", prefix.c_str(), suffix.c_str());
+    }
+
+    int samples = 0;
+    for (;;) {
+        for (auto& bench : benches) {
+            for (int loops = 1; loops < 1000000000;) {
+                bench.b->preDraw(nullptr);
+                auto start = clock::now();
+                    bench.b->draw(loops, nullptr);
+                ns elapsed = clock::now() - start;
+                bench.b->postDraw(nullptr);
+
+                if (elapsed < std::chrono::milliseconds{10}) {
+                    loops *= 2;
+                    continue;
+                }
+
+                bench.best = std::min(bench.best, elapsed / loops);
+                samples++;
+
+                std::sort(benches.begin(), benches.end(), [](const Bench& a, const Bench& b) {
+                    return a.best < b.best;
+                });
+                printf("\r\033[K%d", samples);
+                for (auto& bench : benches) {
+                    if (benches.size() == 1) {
+                        printf("  %s %gns" , bench.name.c_str(), bench.best.count());
+                    } else {
+                        printf("  %s %.3gx", bench.name.c_str(), bench.best / benches[0].best);
+                    }
+                }
+                fflush(stdout);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}