blob: fa99caa1fb56dfff0f043ade0fd7445cab564466 [file] [log] [blame]
joshualitt189aef72015-09-08 07:08:11 -07001/*
2 * Copyright 2015 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 */
8
9#include "VisualLightweightBenchModule.h"
10
11#include "ProcStats.h"
12#include "SkApplication.h"
13#include "SkCanvas.h"
14#include "SkCommandLineFlags.h"
15#include "SkForceLinking.h"
16#include "SkGraphics.h"
17#include "SkGr.h"
18#include "SkImageDecoder.h"
19#include "SkOSFile.h"
20#include "SkStream.h"
21#include "Stats.h"
22#include "gl/GrGLInterface.h"
23
24__SK_FORCE_IMAGE_DECODER_LINKING;
25
26// Between samples we reset context
27// Between frames we swap buffers
joshualitt189aef72015-09-08 07:08:11 -070028DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
joshualitt189aef72015-09-08 07:08:11 -070029DEFINE_string(outResultsFile, "", "If given, write results here as JSON.");
mtkleinca6f43b2015-09-15 13:29:20 -070030DEFINE_string(key, "",
31 "Space-separated key/value pairs to add to JSON identifying this builder.");
joshualitt189aef72015-09-08 07:08:11 -070032DEFINE_string(properties, "",
33 "Space-separated key/value pairs to add to JSON identifying this run.");
joshualitt98d2e2f2015-10-05 07:23:30 -070034DEFINE_int32(samples, 10, "Number of times to time each skp.");
joshualitt189aef72015-09-08 07:08:11 -070035
36static SkString humanize(double ms) {
37 if (FLAGS_verbose) {
38 return SkStringPrintf("%llu", (uint64_t)(ms*1e6));
39 }
40 return HumanizeMs(ms);
41}
42
43#define HUMANIZE(time) humanize(time).c_str()
44
45VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner)
46 : fCurrentSample(0)
joshualitt189aef72015-09-08 07:08:11 -070047 , fOwner(SkRef(owner))
48 , fResults(new ResultsWriter) {
49 fBenchmarkStream.reset(new VisualBenchmarkStream);
50
51 // Print header
joshualitt7d4b4582015-09-24 08:08:23 -070052 SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tbench\n", FLAGS_samples,
53 "samples");
joshualitt189aef72015-09-08 07:08:11 -070054
55 // setup json logging if required
56 if (!FLAGS_outResultsFile.isEmpty()) {
57 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
58 }
59
mtkleinca6f43b2015-09-15 13:29:20 -070060 if (1 == FLAGS_key.count() % 2) {
61 SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
62 } else {
63 for (int i = 1; i < FLAGS_key.count(); i += 2) {
64 fResults->key(FLAGS_key[i - 1], FLAGS_key[i]);
65 }
66 }
67
joshualitt189aef72015-09-08 07:08:11 -070068 if (1 == FLAGS_properties.count() % 2) {
69 SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
70 } else {
71 for (int i = 1; i < FLAGS_properties.count(); i += 2) {
72 fResults->property(FLAGS_properties[i - 1], FLAGS_properties[i]);
73 }
74 }
75}
76
77inline void VisualLightweightBenchModule::renderFrame(SkCanvas* canvas) {
joshualitt98d2e2f2015-10-05 07:23:30 -070078 fBenchmark->draw(fTSM.loops(), canvas);
joshualitt189aef72015-09-08 07:08:11 -070079 canvas->flush();
80 fOwner->present();
81}
82
83void VisualLightweightBenchModule::printStats() {
84 const SkTArray<double>& measurements = fRecords.back().fMeasurements;
85 const char* shortName = fBenchmark->getUniqueName();
86
87 // update log
88 // Note: We currently log only the minimum. It would be interesting to log more information
89 SkString configName;
90 if (FLAGS_msaa > 0) {
91 configName.appendf("msaa_%d", FLAGS_msaa);
92 } else {
93 configName.appendf("gpu");
94 }
95 fResults->config(configName.c_str());
joshualitt7d4b4582015-09-24 08:08:23 -070096 fResults->configOption("name", shortName);
joshualitt189aef72015-09-08 07:08:11 -070097 SkASSERT(measurements.count());
98 Stats stats(measurements);
joshualitt7d4b4582015-09-24 08:08:23 -070099 fResults->metric("min_ms", stats.min);
joshualitt189aef72015-09-08 07:08:11 -0700100
101 // Print output
102 if (FLAGS_verbose) {
103 for (int i = 0; i < measurements.count(); i++) {
104 SkDebugf("%s ", HUMANIZE(measurements[i]));
105 }
106 SkDebugf("%s\n", shortName);
107 } else {
108 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean;
joshualitt7d4b4582015-09-24 08:08:23 -0700109 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\n",
joshualitt189aef72015-09-08 07:08:11 -0700110 sk_tools::getCurrResidentSetSizeMB(),
111 sk_tools::getMaxResidentSetSizeMB(),
joshualitt98d2e2f2015-10-05 07:23:30 -0700112 fTSM.loops(),
joshualitt189aef72015-09-08 07:08:11 -0700113 HUMANIZE(stats.min),
114 HUMANIZE(stats.median),
115 HUMANIZE(stats.mean),
116 HUMANIZE(stats.max),
117 stdDevPercent,
joshualitt7d4b4582015-09-24 08:08:23 -0700118 stats.plot.c_str(),
joshualitt189aef72015-09-08 07:08:11 -0700119 shortName);
120 }
121}
122
123bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) {
124 if (fBenchmark) {
125 return true;
126 }
127
128 fBenchmark.reset(fBenchmarkStream->next());
129 if (!fBenchmark) {
130 return false;
131 }
132
jvanverthf5d1b2d2015-09-15 07:40:56 -0700133 fOwner->clear(canvas, SK_ColorWHITE, 2);
134
joshualitt8a6697a2015-09-30 12:11:07 -0700135 fBenchmark->delayedSetup();
joshualitt189aef72015-09-08 07:08:11 -0700136 fRecords.push_back();
137
138 // Log bench name
139 fResults->bench(fBenchmark->getUniqueName(), fBenchmark->getSize().fX,
140 fBenchmark->getSize().fY);
141 return true;
142}
143
joshualitt189aef72015-09-08 07:08:11 -0700144void VisualLightweightBenchModule::draw(SkCanvas* canvas) {
145 if (!this->advanceRecordIfNecessary(canvas)) {
146 SkDebugf("Exiting VisualBench successfully\n");
147 fOwner->closeWindow();
148 return;
149 }
150 this->renderFrame(canvas);
joshualitt98d2e2f2015-10-05 07:23:30 -0700151 TimingStateMachine::ParentEvents event = fTSM.nextFrame(canvas, fBenchmark);
152 switch (event) {
153 case TimingStateMachine::kReset_ParentEvents:
154 fOwner->reset();
joshualitt7d4b4582015-09-24 08:08:23 -0700155 break;
joshualitt98d2e2f2015-10-05 07:23:30 -0700156 case TimingStateMachine::kTiming_ParentEvents:
joshualitt189aef72015-09-08 07:08:11 -0700157 break;
joshualitt98d2e2f2015-10-05 07:23:30 -0700158 case TimingStateMachine::kTimingFinished_ParentEvents:
159 fOwner->reset();
160 fRecords.back().fMeasurements.push_back(fTSM.lastMeasurement());
161 if (++fCurrentSample > FLAGS_samples) {
162 this->printStats();
163 fTSM.nextBenchmark(canvas, fBenchmark);
164 fCurrentSample = 0;
165 fBenchmark.reset(nullptr);
166 }
joshualitt189aef72015-09-08 07:08:11 -0700167 break;
joshualitt189aef72015-09-08 07:08:11 -0700168 }
joshualitt189aef72015-09-08 07:08:11 -0700169
joshualitt189aef72015-09-08 07:08:11 -0700170}
jvanverthf5d1b2d2015-09-15 07:40:56 -0700171
172bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) {
173 return true;
174}