blob: b909be8a2937513446b24423417106b3b07f7aa4 [file] [log] [blame]
Mike Klein7ac04832017-03-25 11:29:41 -04001/*
2 * Copyright 2017 Google Inc.
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
Mike Klein4f6e2712017-08-11 10:37:35 -04008#include "Benchmark.h"
Florin Malitaab244f02017-05-03 19:16:58 +00009#include "SkData.h"
Mike Klein7ac04832017-03-25 11:29:41 -040010#include "SkOSFile.h"
11#include "SkPicture.h"
Mike Klein4f6e2712017-08-11 10:37:35 -040012#include "Timer.h"
13#include "gm.h"
14#include "ok.h"
15#include <algorithm>
16#include <chrono>
17#include <limits>
Mike Klein042357b2017-08-15 21:55:33 -040018#include <stdlib.h>
Mike Klein7ac04832017-03-25 11:29:41 -040019#include <vector>
20
21struct GMStream : Stream {
22 const skiagm::GMRegistry* registry = skiagm::GMRegistry::Head();
23
24 static std::unique_ptr<Stream> Create(Options) {
25 GMStream stream;
26 return move_unique(stream);
27 }
28
29 struct GMSrc : Src {
30 skiagm::GM* (*factory)(void*);
31 std::unique_ptr<skiagm::GM> gm;
32
Mike Klein0222e702017-03-25 15:53:14 -040033 void init() {
34 if (gm) { return; }
Mike Klein7ac04832017-03-25 11:29:41 -040035 gm.reset(factory(nullptr));
Mike Klein0222e702017-03-25 15:53:14 -040036 }
37
38 std::string name() override {
39 this->init();
Mike Klein7ac04832017-03-25 11:29:41 -040040 return gm->getName();
41 }
42
43 SkISize size() override {
Mike Klein0222e702017-03-25 15:53:14 -040044 this->init();
Mike Klein7ac04832017-03-25 11:29:41 -040045 return gm->getISize();
46 }
47
Mike Kleine15a7b52017-03-29 12:41:13 -040048 Status draw(SkCanvas* canvas) override {
Mike Klein0222e702017-03-25 15:53:14 -040049 this->init();
Mike Klein7ac04832017-03-25 11:29:41 -040050 canvas->clear(0xffffffff);
Mike Klein7ac04832017-03-25 11:29:41 -040051 gm->draw(canvas);
Mike Kleine15a7b52017-03-29 12:41:13 -040052 return Status::OK;
Mike Klein7ac04832017-03-25 11:29:41 -040053 }
54 };
55
56 std::unique_ptr<Src> next() override {
57 if (!registry) {
58 return nullptr;
59 }
60 GMSrc src;
61 src.factory = registry->factory();
62 registry = registry->next();
63 return move_unique(src);
64 }
65};
Mike Kleine15a7b52017-03-29 12:41:13 -040066static Register gm{"gm", "draw GMs linked into this binary", GMStream::Create};
Mike Klein7ac04832017-03-25 11:29:41 -040067
68struct SKPStream : Stream {
69 std::string dir;
70 std::vector<std::string> skps;
71
72 static std::unique_ptr<Stream> Create(Options options) {
73 SKPStream stream;
74 stream.dir = options("dir", "skps");
75 SkOSFile::Iter it{stream.dir.c_str(), ".skp"};
76 for (SkString path; it.next(&path); ) {
77 stream.skps.push_back(path.c_str());
78 }
79 return move_unique(stream);
80 }
81
82 struct SKPSrc : Src {
83 std::string dir, path;
84 sk_sp<SkPicture> pic;
85
Mike Klein0222e702017-03-25 15:53:14 -040086 void init() {
87 if (pic) { return; }
88 auto skp = SkData::MakeFromFileName((dir+"/"+path).c_str());
89 pic = SkPicture::MakeFromData(skp.get());
90 }
91
Mike Klein7ac04832017-03-25 11:29:41 -040092 std::string name() override {
93 return path;
94 }
95
96 SkISize size() override {
Mike Klein0222e702017-03-25 15:53:14 -040097 this->init();
Mike Klein7ac04832017-03-25 11:29:41 -040098 return pic->cullRect().roundOut().size();
99 }
100
Mike Kleine15a7b52017-03-29 12:41:13 -0400101 Status draw(SkCanvas* canvas) override {
Mike Klein0222e702017-03-25 15:53:14 -0400102 this->init();
Mike Klein7ac04832017-03-25 11:29:41 -0400103 canvas->clear(0xffffffff);
104 pic->playback(canvas);
Mike Kleine15a7b52017-03-29 12:41:13 -0400105 return Status::OK;
Mike Klein7ac04832017-03-25 11:29:41 -0400106 }
107 };
108
109 std::unique_ptr<Src> next() override {
110 if (skps.empty()) {
111 return nullptr;
112 }
113 SKPSrc src;
114 src.dir = dir;
115 src.path = skps.back();
116 skps.pop_back();
117 return move_unique(src);
118 }
119};
Mike Kleine15a7b52017-03-29 12:41:13 -0400120static Register skp{"skp", "draw SKPs from dir=skps", SKPStream::Create};
Mike Klein4f6e2712017-08-11 10:37:35 -0400121
122struct BenchStream : Stream {
123 const BenchRegistry* registry = BenchRegistry::Head();
124 int samples;
125
126 static std::unique_ptr<Stream> Create(Options options) {
127 BenchStream stream;
128 stream.samples = std::max(1, atoi(options("samples", "20").c_str()));
129 return move_unique(stream);
130 }
131
132 struct BenchSrc : Src {
133 Benchmark* (*factory)(void*);
134 std::unique_ptr<Benchmark> bench;
135 int samples;
136
137 void init() {
138 if (bench) { return; }
139 bench.reset(factory(nullptr));
140 }
141
142 std::string name() override {
143 this->init();
144 return bench->getName();
145 }
146
147 SkISize size() override {
148 this->init();
149 return { bench->getSize().x(), bench->getSize().y() };
150 }
151
152 Status draw(SkCanvas* canvas) override {
153 this->init();
154
155 using ms = std::chrono::duration<double, std::milli>;
156 std::vector<ms> sample(samples);
157
158 bench->delayedSetup();
159 if (canvas) {
160 bench->perCanvasPreDraw(canvas);
161 }
162 for (int i = 0; i < samples; i++) {
163 using clock = std::chrono::high_resolution_clock;
164 for (int loops = 1; loops < 1000000000; loops *= 2) {
165 bench->preDraw(canvas);
166 auto start = clock::now();
167 bench->draw(loops, canvas);
168 ms elapsed = clock::now() - start;
169 bench->postDraw(canvas);
170
171 if (elapsed.count() < 10) {
172 continue;
173 }
174
175 sample[i] = elapsed / loops;
176 break;
177 }
178 }
179 if (canvas) {
180 bench->perCanvasPostDraw(canvas);
181 }
182
183 std::sort(sample.begin(), sample.end());
184
185 SkString msg = SkStringPrintf("%s\t@0", HumanizeMs(sample[0].count()).c_str());
186 if (samples > 2) {
187 msg.appendf("\t%s\t@%g", HumanizeMs(sample[samples-2].count()).c_str()
188 , 100.0*(samples-1) / samples);
189 }
190 if (samples > 1) {
191 msg.appendf("\t%s\t@100", HumanizeMs(sample[samples-1].count()).c_str());
192 }
193 ok_log(msg.c_str());
194
195 return Status::OK;
196 }
197 };
198
199 std::unique_ptr<Src> next() override {
200 if (!registry) {
201 return nullptr;
202 }
203 BenchSrc src;
204 src.factory = registry->factory();
205 src.samples = samples;
206 registry = registry->next();
207 return move_unique(src);
208 }
209};
210static Register bench{
211 "bench",
212 "time benchmarks linked into this binary samples=20 times each",
213 BenchStream::Create,
214};