Flutter Engine
The Flutter Engine
RasterBenchmarkTarget.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
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 "bench/Benchmark.h"
12
13static DEFINE_int(maxCalibrationAttempts,
14 3,
15 "Try up to this many times to guess loops for a benchmark, or skip the "
16 "benchmark.");
17static DEFINE_double(overheadGoal,
18 0.0001,
19 "Loop until timer overhead is at most this fraction of our measurements.");
20static DEFINE_int(overheadLoops, 100000, "Loops to estimate timer overhead.");
21
22// Defined in BazelBenchmarkTestRunner.cpp.
23SkString humanize(double ms);
24
26
28public:
29 RasterBenchmarkTarget(std::unique_ptr<SurfaceManager> surfaceManager, Benchmark* benchmark)
30 : BenchmarkTarget(std::move(surfaceManager), benchmark) {}
31
33
34 // Based on nanobench's setup_cpu_bench():
35 // https://skia.googlesource.com/skia/+/a063eaeaf1e09e4d6f42e0f44a5723622a46d21c/bench/nanobench.cpp#466.
36 std::tuple<int, bool> autoTuneLoops() const override {
37 // Estimate timer overhead. Based on:
38 // https://skia.googlesource.com/skia/+/a063eaeaf1e09e4d6f42e0f44a5723622a46d21c/bench/nanobench.cpp#402.
39 double overhead = 0;
40 for (int i = 0; i < FLAGS_overheadLoops; i++) {
41 double start = nowMs();
42 overhead += nowMs() - start;
43 }
44 overhead /= FLAGS_overheadLoops;
45
46 // First figure out approximately how many loops of bench it takes to make overhead
47 // negligible.
48 double bench_plus_overhead = 0.0;
49 int round = 0;
50 while (bench_plus_overhead < overhead) {
51 if (round++ == FLAGS_maxCalibrationAttempts) {
52 TestRunner::Log("Warning: Cannot estimate loops for %s (%s vs. %s); skipping.",
54 humanize(bench_plus_overhead).c_str(),
55 humanize(overhead).c_str());
56 return std::make_tuple(0, false);
57 }
58 bench_plus_overhead = time(1);
59 }
60
61 // Later we'll just start and stop the timer once but loop N times.
62 // We'll pick N to make timer overhead negligible:
63 //
64 // overhead
65 // ------------------------- < FLAGS_overheadGoal
66 // overhead + N * Bench Time
67 //
68 // where bench_plus_overhead ~=~ overhead + Bench Time.
69 //
70 // Doing some math, we get:
71 //
72 // (overhead / FLAGS_overheadGoal) - overhead
73 // ------------------------------------------ < N
74 // bench_plus_overhead - overhead)
75 //
76 // Luckily, this also works well in practice. :)
77 const double numer = overhead / FLAGS_overheadGoal - overhead;
78 const double denom = bench_plus_overhead - overhead;
79 int loops = (int)ceil(numer / denom);
80
81 return std::make_tuple(loops, true);
82 }
83};
84
86public:
88
90
93 }
94
95 std::map<std::string, std::string> getKeyValuePairs(std::string cpuName,
96 std::string gpuName) const override {
97 if (cpuName == "") {
98 return std::map<std::string, std::string>();
99 }
100 return {
101 {"cpu_or_gpu", "CPU"},
102 {"cpu_or_gpu_value", cpuName},
103 };
104 }
105};
106
107std::unique_ptr<BenchmarkTarget> BenchmarkTarget::FromConfig(std::string surfaceConfig,
109 if (surfaceConfig == "nonrendering") {
110 return std::make_unique<NonRenderingBenchmarkTarget>(benchmark);
111 }
112
113 std::unique_ptr<SurfaceManager> surfaceManager = SurfaceManager::FromConfig(
114 surfaceConfig, {benchmark->getSize().width(), benchmark->getSize().height()});
115 if (surfaceManager == nullptr) {
116 SK_ABORT("Unknown --surfaceConfig flag value: %s.", surfaceConfig.c_str());
117 }
118
119 return std::make_unique<RasterBenchmarkTarget>(std::move(surfaceManager), benchmark);
120}
static void round(SkPoint *p)
static DEFINE_double(overheadGoal, 0.0001, "Loop until timer overhead is at most this fraction of our measurements.")
static DEFINE_int(maxCalibrationAttempts, 3, "Try up to this many times to guess loops for a benchmark, or skip the " "benchmark.")
SkString humanize(double ms)
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
static std::unique_ptr< BenchmarkTarget > FromConfig(std::string surfaceConfig, Benchmark *benchmark)
Benchmark * fBenchmark
static void printGlobalStats()
double nowMs() const
double time(int loops) const
const char * getUniqueName()
Definition: Benchmark.cpp:22
Benchmark::Backend getBackend() const override
std::map< std::string, std::string > getKeyValuePairs(std::string cpuName, std::string gpuName) const override
SurfaceManager::CpuOrGpu isCpuOrGpuBound() const override
NonRenderingBenchmarkTarget(Benchmark *benchmark)
RasterBenchmarkTarget(std::unique_ptr< SurfaceManager > surfaceManager, Benchmark *benchmark)
std::tuple< int, bool > autoTuneLoops() const override
Benchmark::Backend getBackend() const override
static std::unique_ptr< SurfaceManager > FromConfig(std::string config, SurfaceOptions surfaceOptions)
void Log(const char *format,...) SK_PRINTF_LIKE(1
Definition: TestRunner.cpp:137
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Definition: SkVx.h:702
Definition: ref_ptr.h:256
int32_t width