Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: tools/VisualBench/VisualLightweightBenchModule.cpp

Issue 1358373003: Add warmup bench to visual bench (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweaks Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/VisualBench/VisualLightweightBenchModule.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 * 6 *
7 */ 7 */
8 8
9 #include "VisualLightweightBenchModule.h" 9 #include "VisualLightweightBenchModule.h"
10 10
11 #include "ProcStats.h" 11 #include "ProcStats.h"
12 #include "SkApplication.h" 12 #include "SkApplication.h"
13 #include "SkCanvas.h" 13 #include "SkCanvas.h"
14 #include "SkCommandLineFlags.h" 14 #include "SkCommandLineFlags.h"
15 #include "SkForceLinking.h" 15 #include "SkForceLinking.h"
16 #include "SkGraphics.h" 16 #include "SkGraphics.h"
17 #include "SkGr.h" 17 #include "SkGr.h"
18 #include "SkImageDecoder.h" 18 #include "SkImageDecoder.h"
19 #include "SkOSFile.h" 19 #include "SkOSFile.h"
20 #include "SkStream.h" 20 #include "SkStream.h"
21 #include "Stats.h" 21 #include "Stats.h"
22 #include "gl/GrGLInterface.h" 22 #include "gl/GrGLInterface.h"
23 23
24 __SK_FORCE_IMAGE_DECODER_LINKING; 24 __SK_FORCE_IMAGE_DECODER_LINKING;
25 25
26 // Between samples we reset context 26 // Between samples we reset context
27 // Between frames we swap buffers 27 // Between frames we swap buffers
28 28
29 DEFINE_int32(maxWarmupFrames, 100, "maxmium frames to try and tune for sane timi ngs");
29 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allow s to lag."); 30 DEFINE_int32(gpuFrameLag, 5, "Overestimate of maximum number of frames GPU allow s to lag.");
30 DEFINE_int32(samples, 10, "Number of times to time each skp."); 31 DEFINE_int32(samples, 10, "Number of times to time each skp.");
31 DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample."); 32 DEFINE_int32(frames, 5, "Number of frames of each skp to render per sample.");
32 DEFINE_double(loopMs, 5, "Target loop time in millseconds."); 33 DEFINE_double(loopMs, 5, "Target loop time in millseconds.");
33 DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver."); 34 DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
34 DEFINE_string(outResultsFile, "", "If given, write results here as JSON."); 35 DEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
35 DEFINE_string(key, "", 36 DEFINE_string(key, "",
36 "Space-separated key/value pairs to add to JSON identifying this b uilder."); 37 "Space-separated key/value pairs to add to JSON identifying this b uilder.");
37 DEFINE_string(properties, "", 38 DEFINE_string(properties, "",
38 "Space-separated key/value pairs to add to JSON identifying this r un."); 39 "Space-separated key/value pairs to add to JSON identifying this r un.");
39 40
40 static SkString humanize(double ms) { 41 static SkString humanize(double ms) {
41 if (FLAGS_verbose) { 42 if (FLAGS_verbose) {
42 return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); 43 return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
43 } 44 }
44 return HumanizeMs(ms); 45 return HumanizeMs(ms);
45 } 46 }
46 47
47 #define HUMANIZE(time) humanize(time).c_str() 48 #define HUMANIZE(time) humanize(time).c_str()
48 49
50 // A trivial bench to warm up the gpu
51 class WarmupBench : public Benchmark {
52 public:
53 private:
54 const char* onGetName() override { return "warmupbench"; }
55 void onDraw(const int loops, SkCanvas* canvas) override {
56 for (int i = 0; i < loops; i++) {
57 sk_tool_utils::draw_checkerboard(canvas, 0xffffffff, 0xffc6c3c6, 10) ;
58 }
59 }
60 };
61
49 VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner) 62 VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner)
50 : fCurrentSample(0) 63 : fCurrentSample(0)
51 , fCurrentFrame(0) 64 , fCurrentFrame(0)
52 , fLoops(1) 65 , fLoops(1)
53 , fState(kPreWarmLoops_State) 66 , fState(kWarmup_State)
54 , fBenchmark(nullptr) 67 , fBenchmark(nullptr)
55 , fOwner(SkRef(owner)) 68 , fOwner(SkRef(owner))
56 , fResults(new ResultsWriter) { 69 , fResults(new ResultsWriter) {
57 fBenchmarkStream.reset(new VisualBenchmarkStream); 70 fBenchmarkStream.reset(new VisualBenchmarkStream);
58 71
59 // Print header 72 // Print header
60 SkDebugf("curr/maxrss\tloops\tflushes\tmin\tmedian\tmean\tmax\tstddev\tbench \n"); 73 SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tbench\n" , FLAGS_samples,
74 "samples");
61 75
62 // setup json logging if required 76 // setup json logging if required
63 if (!FLAGS_outResultsFile.isEmpty()) { 77 if (!FLAGS_outResultsFile.isEmpty()) {
64 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0])); 78 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
65 } 79 }
66 80
67 if (1 == FLAGS_key.count() % 2) { 81 if (1 == FLAGS_key.count() % 2) {
68 SkDebugf("ERROR: --key must be passed with an even number of arguments.\ n"); 82 SkDebugf("ERROR: --key must be passed with an even number of arguments.\ n");
69 } else { 83 } else {
70 for (int i = 1; i < FLAGS_key.count(); i += 2) { 84 for (int i = 1; i < FLAGS_key.count(); i += 2) {
(...skipping 22 matching lines...) Expand all
93 107
94 // update log 108 // update log
95 // Note: We currently log only the minimum. It would be interesting to log more information 109 // Note: We currently log only the minimum. It would be interesting to log more information
96 SkString configName; 110 SkString configName;
97 if (FLAGS_msaa > 0) { 111 if (FLAGS_msaa > 0) {
98 configName.appendf("msaa_%d", FLAGS_msaa); 112 configName.appendf("msaa_%d", FLAGS_msaa);
99 } else { 113 } else {
100 configName.appendf("gpu"); 114 configName.appendf("gpu");
101 } 115 }
102 fResults->config(configName.c_str()); 116 fResults->config(configName.c_str());
103 fResults->configOption("name", fBenchmark->getUniqueName()); 117 fResults->configOption("name", shortName);
104 SkASSERT(measurements.count()); 118 SkASSERT(measurements.count());
105 Stats stats(measurements); 119 Stats stats(measurements);
106 fResults->metric("min_ms", stats.min); 120 fResults->metric("min_ms", stats.min);
107 121
108 // Print output 122 // Print output
109 if (FLAGS_verbose) { 123 if (FLAGS_verbose) {
110 for (int i = 0; i < measurements.count(); i++) { 124 for (int i = 0; i < measurements.count(); i++) {
111 SkDebugf("%s ", HUMANIZE(measurements[i])); 125 SkDebugf("%s ", HUMANIZE(measurements[i]));
112 } 126 }
113 SkDebugf("%s\n", shortName); 127 SkDebugf("%s\n", shortName);
114 } else { 128 } else {
115 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean; 129 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean;
116 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\n", 130 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\n",
117 sk_tools::getCurrResidentSetSizeMB(), 131 sk_tools::getCurrResidentSetSizeMB(),
118 sk_tools::getMaxResidentSetSizeMB(), 132 sk_tools::getMaxResidentSetSizeMB(),
119 fLoops, 133 fLoops,
120 HUMANIZE(stats.min), 134 HUMANIZE(stats.min),
121 HUMANIZE(stats.median), 135 HUMANIZE(stats.median),
122 HUMANIZE(stats.mean), 136 HUMANIZE(stats.mean),
123 HUMANIZE(stats.max), 137 HUMANIZE(stats.max),
124 stdDevPercent, 138 stdDevPercent,
139 stats.plot.c_str(),
125 shortName); 140 shortName);
126 } 141 }
127 } 142 }
128 143
129 bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) { 144 bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) {
145 if (!fBenchmark && fState == kWarmup_State) {
146 fBenchmark.reset(new WarmupBench);
147 return true;
148 }
149
130 if (fBenchmark) { 150 if (fBenchmark) {
131 return true; 151 return true;
132 } 152 }
133 153
134 fBenchmark.reset(fBenchmarkStream->next()); 154 fBenchmark.reset(fBenchmarkStream->next());
135 if (!fBenchmark) { 155 if (!fBenchmark) {
136 return false; 156 return false;
137 } 157 }
138 158
139 fOwner->clear(canvas, SK_ColorWHITE, 2); 159 fOwner->clear(canvas, SK_ColorWHITE, 2);
140 160
141
142 fBenchmark->preDraw(); 161 fBenchmark->preDraw();
143 fRecords.push_back(); 162 fRecords.push_back();
144 163
145 // Log bench name 164 // Log bench name
146 fResults->bench(fBenchmark->getUniqueName(), fBenchmark->getSize().fX, 165 fResults->bench(fBenchmark->getUniqueName(), fBenchmark->getSize().fX,
147 fBenchmark->getSize().fY); 166 fBenchmark->getSize().fY);
148 return true; 167 return true;
149 } 168 }
150 169
151 inline void VisualLightweightBenchModule::nextState(State nextState) { 170 inline void VisualLightweightBenchModule::nextState(State nextState) {
152 fState = nextState; 171 fState = nextState;
153 } 172 }
154 173
155 void VisualLightweightBenchModule::perCanvasPreDraw(SkCanvas* canvas, State next State) { 174 void VisualLightweightBenchModule::perCanvasPreDraw(SkCanvas* canvas, State next State) {
156 fBenchmark->perCanvasPreDraw(canvas); 175 fBenchmark->perCanvasPreDraw(canvas);
157 fCurrentFrame = 0; 176 fCurrentFrame = 0;
158 this->nextState(nextState); 177 this->nextState(nextState);
159 } 178 }
160 179
180 void VisualLightweightBenchModule::warmup(SkCanvas* canvas) {
181 if (fCurrentFrame >= FLAGS_maxWarmupFrames) {
182 this->nextState(kPreWarmLoopsPerCanvasPreDraw_State);
183 fBenchmark.reset(nullptr);
184 this->resetTimingState();
185 fLoops = 1;
186 } else {
187 bool isEven = (fCurrentFrame++ % 2) == 0;
188 if (isEven) {
189 fTimer.start();
190 } else {
191 double elapsedMs = this->elapsed();
192 if (elapsedMs < FLAGS_loopMs) {
193 fLoops *= 2;
194 }
195 fTimer = WallTimer();
196 fOwner->reset();
197 }
198 }
199 }
200
161 void VisualLightweightBenchModule::preWarm(State nextState) { 201 void VisualLightweightBenchModule::preWarm(State nextState) {
162 if (fCurrentFrame >= FLAGS_gpuFrameLag) { 202 if (fCurrentFrame >= FLAGS_gpuFrameLag) {
163 // we currently time across all frames to make sure we capture all GPU w ork 203 // we currently time across all frames to make sure we capture all GPU w ork
164 this->nextState(nextState); 204 this->nextState(nextState);
165 fCurrentFrame = 0; 205 fCurrentFrame = 0;
166 fTimer.start(); 206 fTimer.start();
167 } else { 207 } else {
168 fCurrentFrame++; 208 fCurrentFrame++;
169 } 209 }
170 } 210 }
171 211
172 void VisualLightweightBenchModule::draw(SkCanvas* canvas) { 212 void VisualLightweightBenchModule::draw(SkCanvas* canvas) {
173 if (!this->advanceRecordIfNecessary(canvas)) { 213 if (!this->advanceRecordIfNecessary(canvas)) {
174 SkDebugf("Exiting VisualBench successfully\n"); 214 SkDebugf("Exiting VisualBench successfully\n");
175 fOwner->closeWindow(); 215 fOwner->closeWindow();
176 return; 216 return;
177 } 217 }
178 this->renderFrame(canvas); 218 this->renderFrame(canvas);
179 switch (fState) { 219 switch (fState) {
220 case kWarmup_State: {
221 this->warmup(canvas);
222 break;
223 }
180 case kPreWarmLoopsPerCanvasPreDraw_State: { 224 case kPreWarmLoopsPerCanvasPreDraw_State: {
181 this->perCanvasPreDraw(canvas, kPreWarmLoops_State); 225 this->perCanvasPreDraw(canvas, kPreWarmLoops_State);
182 break; 226 break;
183 } 227 }
184 case kPreWarmLoops_State: { 228 case kPreWarmLoops_State: {
185 this->preWarm(kTuneLoops_State); 229 this->preWarm(kTuneLoops_State);
186 break; 230 break;
187 } 231 }
188 case kTuneLoops_State: { 232 case kTuneLoops_State: {
189 this->tuneLoops(); 233 this->tuneLoops();
(...skipping 27 matching lines...) Expand all
217 261
218 void VisualLightweightBenchModule::scaleLoops(double elapsedMs) { 262 void VisualLightweightBenchModule::scaleLoops(double elapsedMs) {
219 // Scale back the number of loops 263 // Scale back the number of loops
220 fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsedMs); 264 fLoops = (int)ceil(fLoops * FLAGS_loopMs / elapsedMs);
221 } 265 }
222 266
223 inline void VisualLightweightBenchModule::tuneLoops() { 267 inline void VisualLightweightBenchModule::tuneLoops() {
224 if (1 << 30 == fLoops) { 268 if (1 << 30 == fLoops) {
225 // We're about to wrap. Something's wrong with the bench. 269 // We're about to wrap. Something's wrong with the bench.
226 SkDebugf("InnerLoops wrapped\n"); 270 SkDebugf("InnerLoops wrapped\n");
227 fLoops = 0; 271 fLoops = 1;
228 } else { 272 } else {
229 double elapsedMs = this->elapsed(); 273 double elapsedMs = this->elapsed();
230 if (elapsedMs > FLAGS_loopMs) { 274 if (elapsedMs > FLAGS_loopMs) {
231 this->scaleLoops(elapsedMs); 275 this->scaleLoops(elapsedMs);
232 this->nextState(kPreWarmTimingPerCanvasPreDraw_State); 276 this->nextState(kPreWarmTimingPerCanvasPreDraw_State);
233 } else { 277 } else {
234 fLoops *= 2; 278 fLoops *= 2;
235 this->nextState(kPreWarmLoops_State); 279 this->nextState(kPreWarmLoops_State);
236 } 280 }
237 this->resetTimingState(); 281 this->resetTimingState();
(...skipping 24 matching lines...) Expand all
262 } 306 }
263 this->resetTimingState(); 307 this->resetTimingState();
264 } else { 308 } else {
265 fCurrentFrame++; 309 fCurrentFrame++;
266 } 310 }
267 } 311 }
268 312
269 bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) { 313 bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) {
270 return true; 314 return true;
271 } 315 }
OLDNEW
« no previous file with comments | « tools/VisualBench/VisualLightweightBenchModule.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698