/* * 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 "OverwriteLine.h" #include "SkGraphics.h" #include "SkTaskGroup.h" #include #include #include #include #include #include #include #if defined(SK_BUILD_FOR_WIN32) static const char* kEllipsis = "..."; #else static const char* kEllipsis = "…"; #endif int main(int argc, char** argv) { SkGraphics::Init(); SkTaskGroup::Enabler enabled; using clock = std::chrono::high_resolution_clock; using ns = std::chrono::duration; std::regex pattern; int limit = 2147483647; if (argc > 1) { pattern = argv[1]; } if (argc > 2) { limit = atoi(argv[2]); } struct Bench { std::unique_ptr b; std::string name; ns best; }; std::vector benches; for (auto r = BenchRegistry::Head(); r; r = r->next()) { std::unique_ptr 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{std::numeric_limits::infinity()}}); } } if (benches.size() == 0) { SkDebugf("No bench matched.\n"); return 1; } 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, kEllipsis); } } 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, kEllipsis); } } SkDebugf("%s%s%s\n", prefix.c_str(), kEllipsis, suffix.c_str()); } int samples = 0; while (samples < limit) { std::random_shuffle(benches.begin(), benches.end()); 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++; struct Result { const char* name; ns best; }; std::vector sorted(benches.size()); for (size_t i = 0; i < benches.size(); i++) { sorted[i].name = benches[i].name.c_str(); sorted[i].best = benches[i].best; } std::sort(sorted.begin(), sorted.end(), [](const Result& a, const Result& b) { return a.best < b.best; }); SkDebugf("%s%d", kSkOverwriteLine, samples); for (auto& result : sorted) { if (sorted.size() == 1) { SkDebugf(" %s %gns" , result.name, result.best.count()); } else { SkDebugf(" %s %.3gx", result.name, result.best / sorted[0].best); } } break; } } } return 0; }