• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "Benchmark.h"
9 #include "OverwriteLine.h"
10 #include "SkGraphics.h"
11 #include "SkTaskGroup.h"
12 #include <algorithm>
13 #include <chrono>
14 #include <limits>
15 #include <regex>
16 #include <stdlib.h>
17 #include <string>
18 #include <vector>
19 
20 
21 #if defined(SK_BUILD_FOR_WIN32)
22 static const char* kEllipsis = "...";
23 #else
24 static const char* kEllipsis = "…";
25 #endif
26 
main(int argc,char ** argv)27 int main(int argc, char** argv) {
28     SkGraphics::Init();
29     SkTaskGroup::Enabler enabled;
30 
31     using clock = std::chrono::high_resolution_clock;
32     using ns = std::chrono::duration<double, std::nano>;
33 
34     std::regex pattern;
35     int limit = 2147483647;
36     if (argc > 1) { pattern = argv[1]; }
37     if (argc > 2) { limit = atoi(argv[2]); }
38 
39     struct Bench {
40         std::unique_ptr<Benchmark> b;
41         std::string                name;
42         ns                         best;
43     };
44     std::vector<Bench> benches;
45 
46     for (auto r = BenchRegistry::Head(); r; r = r->next()) {
47         std::unique_ptr<Benchmark> bench{ r->factory()(nullptr) };
48 
49         std::string name = bench->getName();
50         if (std::regex_search(name, pattern) &&
51                 bench->isSuitableFor(Benchmark::kNonRendering_Backend)) {
52             bench->delayedSetup();
53             benches.emplace_back(Bench{std::move(bench), name,
54                                        ns{std::numeric_limits<double>::infinity()}});
55         }
56     }
57 
58     if (benches.size() == 0) {
59         SkDebugf("No bench matched.\n");
60         return 1;
61     }
62 
63     if (benches.size() > 1) {
64         int common_prefix = benches[0].name.size();
65         for (size_t i = 1; i < benches.size(); i++) {
66             int len = std::mismatch(benches[i-1].name.begin(), benches[i-1].name.end(),
67                                     benches[i-0].name.begin())
68                 .first - benches[i-1].name.begin();
69             common_prefix = std::min(common_prefix, len);
70         }
71         std::string prefix = benches[0].name.substr(0, common_prefix);
72         if (common_prefix) {
73             for (auto& bench : benches) {
74                 bench.name.replace(0, common_prefix, kEllipsis);
75             }
76         }
77 
78         int common_suffix = benches[0].name.size();
79         for (size_t i = 1; i < benches.size(); i++) {
80             int len = std::mismatch(benches[i-1].name.rbegin(), benches[i-1].name.rend(),
81                                     benches[i-0].name.rbegin())
82                 .first - benches[i-1].name.rbegin();
83             common_suffix = std::min(common_suffix, len);
84         }
85         std::string suffix = benches[0].name.substr(benches[0].name.size() - common_suffix);
86         if (common_suffix) {
87             for (auto& bench : benches) {
88                 bench.name.replace(bench.name.size() - common_suffix, common_suffix, kEllipsis);
89             }
90         }
91 
92         SkDebugf("%s%s%s\n", prefix.c_str(), kEllipsis, suffix.c_str());
93     }
94 
95     int samples = 0;
96     while (samples < limit) {
97         std::random_shuffle(benches.begin(), benches.end());
98         for (auto& bench : benches) {
99             for (int loops = 1; loops < 1000000000;) {
100                 bench.b->preDraw(nullptr);
101                 auto start = clock::now();
102                     bench.b->draw(loops, nullptr);
103                 ns elapsed = clock::now() - start;
104                 bench.b->postDraw(nullptr);
105 
106                 if (elapsed < std::chrono::milliseconds{10}) {
107                     loops *= 2;
108                     continue;
109                 }
110 
111                 bench.best = std::min(bench.best, elapsed / loops);
112                 samples++;
113 
114                 struct Result { const char* name; ns best; };
115                 std::vector<Result> sorted(benches.size());
116                 for (size_t i = 0; i < benches.size(); i++) {
117                     sorted[i].name = benches[i].name.c_str();
118                     sorted[i].best = benches[i].best;
119                 }
120                 std::sort(sorted.begin(), sorted.end(), [](const Result& a, const Result& b) {
121                     return a.best < b.best;
122                 });
123 
124                 SkDebugf("%s%d", kSkOverwriteLine, samples);
125                 for (auto& result : sorted) {
126                     if (sorted.size() == 1) {
127                         SkDebugf("  %s %gns" , result.name, result.best.count());
128                     } else {
129                         SkDebugf("  %s %.3gx", result.name, result.best / sorted[0].best);
130                     }
131                 }
132                 break;
133             }
134         }
135     }
136 
137     return 0;
138 }
139