blob: e2942d18bdc36f2647b899b1042f33a4d4ef37cd [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)
joshualittcb54e8e2015-10-05 13:58:26 -070047 , fHasBeenReset(false)
joshualitt189aef72015-09-08 07:08:11 -070048 , fOwner(SkRef(owner))
49 , fResults(new ResultsWriter) {
50 fBenchmarkStream.reset(new VisualBenchmarkStream);
51
52 // Print header
joshualitt7d4b4582015-09-24 08:08:23 -070053 SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tbench\n", FLAGS_samples,
54 "samples");
joshualitt189aef72015-09-08 07:08:11 -070055
56 // setup json logging if required
57 if (!FLAGS_outResultsFile.isEmpty()) {
58 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0]));
59 }
60
mtkleinca6f43b2015-09-15 13:29:20 -070061 if (1 == FLAGS_key.count() % 2) {
62 SkDebugf("ERROR: --key must be passed with an even number of arguments.\n");
63 } else {
64 for (int i = 1; i < FLAGS_key.count(); i += 2) {
65 fResults->key(FLAGS_key[i - 1], FLAGS_key[i]);
66 }
67 }
68
joshualitt189aef72015-09-08 07:08:11 -070069 if (1 == FLAGS_properties.count() % 2) {
70 SkDebugf("ERROR: --properties must be passed with an even number of arguments.\n");
71 } else {
72 for (int i = 1; i < FLAGS_properties.count(); i += 2) {
73 fResults->property(FLAGS_properties[i - 1], FLAGS_properties[i]);
74 }
75 }
76}
77
78inline void VisualLightweightBenchModule::renderFrame(SkCanvas* canvas) {
joshualitt98d2e2f2015-10-05 07:23:30 -070079 fBenchmark->draw(fTSM.loops(), canvas);
joshualitt189aef72015-09-08 07:08:11 -070080 canvas->flush();
81 fOwner->present();
82}
83
84void VisualLightweightBenchModule::printStats() {
85 const SkTArray<double>& measurements = fRecords.back().fMeasurements;
86 const char* shortName = fBenchmark->getUniqueName();
87
88 // update log
89 // Note: We currently log only the minimum. It would be interesting to log more information
90 SkString configName;
91 if (FLAGS_msaa > 0) {
92 configName.appendf("msaa_%d", FLAGS_msaa);
93 } else {
94 configName.appendf("gpu");
95 }
96 fResults->config(configName.c_str());
joshualitt7d4b4582015-09-24 08:08:23 -070097 fResults->configOption("name", shortName);
joshualitt189aef72015-09-08 07:08:11 -070098 SkASSERT(measurements.count());
99 Stats stats(measurements);
joshualitt7d4b4582015-09-24 08:08:23 -0700100 fResults->metric("min_ms", stats.min);
joshualitt189aef72015-09-08 07:08:11 -0700101
102 // Print output
103 if (FLAGS_verbose) {
104 for (int i = 0; i < measurements.count(); i++) {
105 SkDebugf("%s ", HUMANIZE(measurements[i]));
106 }
107 SkDebugf("%s\n", shortName);
108 } else {
109 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean;
joshualitt7d4b4582015-09-24 08:08:23 -0700110 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 -0700111 sk_tools::getCurrResidentSetSizeMB(),
112 sk_tools::getMaxResidentSetSizeMB(),
joshualitt98d2e2f2015-10-05 07:23:30 -0700113 fTSM.loops(),
joshualitt189aef72015-09-08 07:08:11 -0700114 HUMANIZE(stats.min),
115 HUMANIZE(stats.median),
116 HUMANIZE(stats.mean),
117 HUMANIZE(stats.max),
118 stdDevPercent,
joshualitt7d4b4582015-09-24 08:08:23 -0700119 stats.plot.c_str(),
joshualitt189aef72015-09-08 07:08:11 -0700120 shortName);
121 }
122}
123
124bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) {
125 if (fBenchmark) {
126 return true;
127 }
128
129 fBenchmark.reset(fBenchmarkStream->next());
130 if (!fBenchmark) {
131 return false;
132 }
133
jvanverthf5d1b2d2015-09-15 07:40:56 -0700134 fOwner->clear(canvas, SK_ColorWHITE, 2);
135
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);
joshualittcb54e8e2015-10-05 13:58:26 -0700141
142 fBenchmark->delayedSetup();
143 fBenchmark->preTimingHooks(canvas);
joshualitt189aef72015-09-08 07:08:11 -0700144 return true;
145}
146
joshualitt189aef72015-09-08 07:08:11 -0700147void VisualLightweightBenchModule::draw(SkCanvas* canvas) {
148 if (!this->advanceRecordIfNecessary(canvas)) {
149 SkDebugf("Exiting VisualBench successfully\n");
150 fOwner->closeWindow();
151 return;
152 }
joshualittcb54e8e2015-10-05 13:58:26 -0700153
154 if (fHasBeenReset) {
155 fHasBeenReset = false;
156 fBenchmark->preTimingHooks(canvas);
157 }
158
joshualitt189aef72015-09-08 07:08:11 -0700159 this->renderFrame(canvas);
joshualittcb54e8e2015-10-05 13:58:26 -0700160 TimingStateMachine::ParentEvents event = fTSM.nextFrame(true);
joshualitt98d2e2f2015-10-05 07:23:30 -0700161 switch (event) {
162 case TimingStateMachine::kReset_ParentEvents:
joshualittcb54e8e2015-10-05 13:58:26 -0700163 fBenchmark->postTimingHooks(canvas);
joshualitt98d2e2f2015-10-05 07:23:30 -0700164 fOwner->reset();
joshualittcb54e8e2015-10-05 13:58:26 -0700165 fHasBeenReset = true;
joshualitt7d4b4582015-09-24 08:08:23 -0700166 break;
joshualitt98d2e2f2015-10-05 07:23:30 -0700167 case TimingStateMachine::kTiming_ParentEvents:
joshualitt189aef72015-09-08 07:08:11 -0700168 break;
joshualitt98d2e2f2015-10-05 07:23:30 -0700169 case TimingStateMachine::kTimingFinished_ParentEvents:
joshualittcb54e8e2015-10-05 13:58:26 -0700170 fBenchmark->postTimingHooks(canvas);
joshualitt98d2e2f2015-10-05 07:23:30 -0700171 fOwner->reset();
172 fRecords.back().fMeasurements.push_back(fTSM.lastMeasurement());
173 if (++fCurrentSample > FLAGS_samples) {
174 this->printStats();
175 fTSM.nextBenchmark(canvas, fBenchmark);
176 fCurrentSample = 0;
177 fBenchmark.reset(nullptr);
joshualittdc5db592015-10-05 13:24:55 -0700178 } else {
joshualittcb54e8e2015-10-05 13:58:26 -0700179 fHasBeenReset = true;
joshualitt98d2e2f2015-10-05 07:23:30 -0700180 }
joshualitt189aef72015-09-08 07:08:11 -0700181 break;
joshualitt189aef72015-09-08 07:08:11 -0700182 }
joshualitt189aef72015-09-08 07:08:11 -0700183}
jvanverthf5d1b2d2015-09-15 07:40:56 -0700184
185bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) {
186 return true;
187}