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