aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/monobench.cpp
blob: 88a6cce37c9adaf8508d1f9df2fff25ab73e0a40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
 * 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 "SkTaskGroup.h"
#include <algorithm>
#include <chrono>
#include <regex>
#include <stdio.h>
#include <string>
#include <vector>

int main(int argc, char** argv) {
    SkGraphics::Init();
    SkTaskGroup::Enabler enabled;

    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;
}