17e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein/*
27e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein * Copyright 2016 Google Inc.
37e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein *
47e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein * Use of this source code is governed by a BSD-style license that can be
57e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein * found in the LICENSE file.
67e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein */
77e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
87e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include "Benchmark.h"
94bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein#include "OverwriteLine.h"
107e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include "SkGraphics.h"
112052f313f0fa16daae86e6f298e12e6f23604036mtklein#include "SkTaskGroup.h"
127e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include <algorithm>
137e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include <chrono>
14cc300a15d49f6c62c32935b40f5b86d681aff845Mike Klein#include <limits>
157e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include <regex>
16645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein#include <stdlib.h>
177e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include <string>
187e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein#include <vector>
197e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
204bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein
214bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein#if defined(SK_BUILD_FOR_WIN32)
224bc6d8fd3d0586444d743b07975a492cb6305448Mike Kleinstatic const char* kEllipsis = "...";
234bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein#else
244bc6d8fd3d0586444d743b07975a492cb6305448Mike Kleinstatic const char* kEllipsis = "…";
254bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein#endif
264bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein
277e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtkleinint main(int argc, char** argv) {
287e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    SkGraphics::Init();
292052f313f0fa16daae86e6f298e12e6f23604036mtklein    SkTaskGroup::Enabler enabled;
307e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
317e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    using clock = std::chrono::high_resolution_clock;
327e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    using ns = std::chrono::duration<double, std::nano>;
337e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
347e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    std::regex pattern;
35645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein    int limit = 2147483647;
36645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein    if (argc > 1) { pattern = argv[1]; }
37645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein    if (argc > 2) { limit = atoi(argv[2]); }
387e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
397e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    struct Bench {
407e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        std::unique_ptr<Benchmark> b;
417e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        std::string                name;
427e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        ns                         best;
437e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    };
447e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    std::vector<Bench> benches;
457e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
467e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    for (auto r = BenchRegistry::Head(); r; r = r->next()) {
477e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        std::unique_ptr<Benchmark> bench{ r->factory()(nullptr) };
487e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
497e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        std::string name = bench->getName();
507e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        if (std::regex_search(name, pattern) &&
517e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                bench->isSuitableFor(Benchmark::kNonRendering_Backend)) {
527e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            bench->delayedSetup();
53cc300a15d49f6c62c32935b40f5b86d681aff845Mike Klein            benches.emplace_back(Bench{std::move(bench), name,
54cc300a15d49f6c62c32935b40f5b86d681aff845Mike Klein                                       ns{std::numeric_limits<double>::infinity()}});
557e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        }
567e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    }
577e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
58645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein    if (benches.size() == 0) {
594bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein        SkDebugf("No bench matched.\n");
60645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein        return 1;
61645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein    }
62645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein
637e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    if (benches.size() > 1) {
647e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        int common_prefix = benches[0].name.size();
657e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        for (size_t i = 1; i < benches.size(); i++) {
667e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            int len = std::mismatch(benches[i-1].name.begin(), benches[i-1].name.end(),
677e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                                    benches[i-0].name.begin())
687e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                .first - benches[i-1].name.begin();
697e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            common_prefix = std::min(common_prefix, len);
707e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        }
717e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        std::string prefix = benches[0].name.substr(0, common_prefix);
727e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        if (common_prefix) {
737e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            for (auto& bench : benches) {
744bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein                bench.name.replace(0, common_prefix, kEllipsis);
757e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            }
767e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        }
777e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
787e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        int common_suffix = benches[0].name.size();
797e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        for (size_t i = 1; i < benches.size(); i++) {
807e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            int len = std::mismatch(benches[i-1].name.rbegin(), benches[i-1].name.rend(),
817e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                                    benches[i-0].name.rbegin())
827e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                .first - benches[i-1].name.rbegin();
837e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            common_suffix = std::min(common_suffix, len);
847e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        }
857e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        std::string suffix = benches[0].name.substr(benches[0].name.size() - common_suffix);
867e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        if (common_suffix) {
877e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            for (auto& bench : benches) {
884bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein                bench.name.replace(bench.name.size() - common_suffix, common_suffix, kEllipsis);
897e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            }
907e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        }
917e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
924bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein        SkDebugf("%s%s%s\n", prefix.c_str(), kEllipsis, suffix.c_str());
937e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    }
947e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
957e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    int samples = 0;
96645999fe7808fa7bdbb6df6dfcbbeb974d1de933Mike Klein    while (samples < limit) {
977c6bc4616cee740b197e4e8f2b704b3f55fd8e6dMike Klein        std::random_shuffle(benches.begin(), benches.end());
987e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        for (auto& bench : benches) {
997e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            for (int loops = 1; loops < 1000000000;) {
1007e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                bench.b->preDraw(nullptr);
1017e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                auto start = clock::now();
1027e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                    bench.b->draw(loops, nullptr);
1037e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                ns elapsed = clock::now() - start;
1047e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                bench.b->postDraw(nullptr);
1057e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
1067e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                if (elapsed < std::chrono::milliseconds{10}) {
1077e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                    loops *= 2;
1087e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                    continue;
1097e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                }
1107e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
1117e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                bench.best = std::min(bench.best, elapsed / loops);
1127e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                samples++;
1137e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
114ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                struct Result { const char* name; ns best; };
115ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                std::vector<Result> sorted(benches.size());
116ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                for (size_t i = 0; i < benches.size(); i++) {
117ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                    sorted[i].name = benches[i].name.c_str();
118ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                    sorted[i].best = benches[i].best;
119ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                }
120ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                std::sort(sorted.begin(), sorted.end(), [](const Result& a, const Result& b) {
1217e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                    return a.best < b.best;
1227e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                });
123ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein
1244bc6d8fd3d0586444d743b07975a492cb6305448Mike Klein                SkDebugf("%s%d", kSkOverwriteLine, samples);
125ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                for (auto& result : sorted) {
126ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                    if (sorted.size() == 1) {
127ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                        SkDebugf("  %s %gns" , result.name, result.best.count());
1287e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                    } else {
129ef6bbbd06374cf7ef175c780ec9ac87c43386532Mike Klein                        SkDebugf("  %s %.3gx", result.name, result.best / sorted[0].best);
1307e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                    }
1317e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                }
1327e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein                break;
1337e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein            }
1347e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein        }
1357e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    }
1367e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein
1377e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein    return 0;
1387e602c2c6cb2fbeb70a3978e2148844b673a8a4cmtklein}
139