xref: /aosp_15_r20/external/skia/tools/testrunners/benchmark/target/BenchmarkTarget.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkSurface.h"
11 #include "tools/testrunners/common/surface_manager/SurfaceManager.h"
12 
13 #include <memory>
14 #include <tuple>
15 
16 // Represents a target against which to time a benchmark. Provides an SkCanvas and all necessary
17 // timing methods.
18 //
19 // Based on nanobench's Target struct:
20 // https://skia.googlesource.com/skia/+/a063eaeaf1e09e4d6f42e0f44a5723622a46d21c/bench/nanobench.h#36.
21 class BenchmarkTarget {
22 public:
23     static std::unique_ptr<BenchmarkTarget> FromConfig(std::string surfaceConfig,
24                                                        Benchmark* benchmark);
25 
26     // Prints to standard output overall statistics collected from all benchmark targets
27     // instantiated during the lifetime of the test runner.
28     static void printGlobalStats();
29 
30     virtual ~BenchmarkTarget() = default;
31 
32     // Returns the backend used by this benchmark target.
33     virtual Benchmark::Backend getBackend() const = 0;
34 
35     // Should be called once, immediately before any timing or drawing.
36     virtual void setup() const;
37 
38     // Estimates the number of required benchmark runs to get a meaningful measurement. Returns
39     // the estimated number of runs, and a boolean indicating success or failure.
40     virtual std::tuple<int, bool> autoTuneLoops() const = 0;
41 
42     // Should be called once, immediately before any timing or drawing. Implementations may time
43     // the benchmark for the passed in number of loops multiple times until a steady state is
44     // reached.
warmUp(int loops)45     virtual void warmUp(int loops) const {}
46 
47     // Times the benchmark by drawing for the given number of interations. Returns the number of
48     // milliseconds elapsed. It can be called multiple times between the setup() and tearDown()
49     // calls.
50     double time(int loops) const;
51 
52     // Should be called once after the test runner is done with the benchmark.
53     void tearDown() const;
54 
55     // Produces statistics that test runner should include in the output JSON file.
dumpStats(skia_private::TArray<SkString> * keys,skia_private::TArray<double> * values)56     virtual void dumpStats(skia_private::TArray<SkString>* keys,
57                            skia_private::TArray<double>* values) const {}
58 
59     // Prints various statistics to standard output.
printStats()60     virtual void printStats() const {}
61 
62     SkCanvas* getCanvas() const;
63 
64     Benchmark* getBenchmark() const;
65 
66     // Returns the subset of Perf key/value pairs that are determined by the surface config. The
67     // returned map includes keys "cpu_or_gpu" and "cpu_or_gpu_value", which are populated based
68     // on the cpuName and gpuName arguments, and whether the surface config is CPU or GPU bound.
69     virtual std::map<std::string, std::string> getKeyValuePairs(std::string cpuName,
70                                                                 std::string gpuName) const;
71 
72     // Returns an enum indicating whether the surface is CPU or GPU bound.
73     virtual SurfaceManager::CpuOrGpu isCpuOrGpuBound() const;
74 
75 protected:
BenchmarkTarget(std::unique_ptr<SurfaceManager> surfaceManager,Benchmark * benchmark)76     BenchmarkTarget(std::unique_ptr<SurfaceManager> surfaceManager, Benchmark* benchmark)
77             : fSurfaceManager(std::move(surfaceManager)), fBenchmark(benchmark) {}
78 
79     // Called *after* the clock timer is started, before the benchmark is drawn. Most backends just
80     // return the canvas passed in, but some may replace it.
onBeforeDraw(SkCanvas * canvas)81     virtual SkCanvas* onBeforeDraw(SkCanvas* canvas) const { return canvas; }
82 
83     // Called *after* a benchmark is drawn, but before the clock timer is stopped.
onAfterDraw()84     virtual void onAfterDraw() const {}
85 
86     double nowMs() const;
87 
88     std::unique_ptr<SurfaceManager> fSurfaceManager;
89     Benchmark* fBenchmark;
90 };
91