OLD | NEW |
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 |
(...skipping 25 matching lines...) Expand all Loading... |
36 static SkString humanize(double ms) { | 36 static SkString humanize(double ms) { |
37 if (FLAGS_verbose) { | 37 if (FLAGS_verbose) { |
38 return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); | 38 return SkStringPrintf("%llu", (uint64_t)(ms*1e6)); |
39 } | 39 } |
40 return HumanizeMs(ms); | 40 return HumanizeMs(ms); |
41 } | 41 } |
42 | 42 |
43 #define HUMANIZE(time) humanize(time).c_str() | 43 #define HUMANIZE(time) humanize(time).c_str() |
44 | 44 |
45 VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner) | 45 VisualLightweightBenchModule::VisualLightweightBenchModule(VisualBench* owner) |
46 : fCurrentSample(0) | 46 : INHERITED(owner, true) |
47 , fHasBeenReset(false) | 47 , fCurrentSample(0) |
48 , fOwner(SkRef(owner)) | |
49 , fResults(new ResultsWriter) { | 48 , fResults(new ResultsWriter) { |
50 fBenchmarkStream.reset(new VisualBenchmarkStream); | |
51 | |
52 // Print header | 49 // Print header |
53 SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tbench\n"
, FLAGS_samples, | 50 SkDebugf("curr/maxrss\tloops\tmin\tmedian\tmean\tmax\tstddev\t%-*s\tbench\n"
, FLAGS_samples, |
54 "samples"); | 51 "samples"); |
55 | 52 |
56 // setup json logging if required | 53 // setup json logging if required |
57 if (!FLAGS_outResultsFile.isEmpty()) { | 54 if (!FLAGS_outResultsFile.isEmpty()) { |
58 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0])); | 55 fResults.reset(new NanoJSONResultsWriter(FLAGS_outResultsFile[0])); |
59 } | 56 } |
60 | 57 |
61 if (1 == FLAGS_key.count() % 2) { | 58 if (1 == FLAGS_key.count() % 2) { |
62 SkDebugf("ERROR: --key must be passed with an even number of arguments.\
n"); | 59 SkDebugf("ERROR: --key must be passed with an even number of arguments.\
n"); |
63 } else { | 60 } else { |
64 for (int i = 1; i < FLAGS_key.count(); i += 2) { | 61 for (int i = 1; i < FLAGS_key.count(); i += 2) { |
65 fResults->key(FLAGS_key[i - 1], FLAGS_key[i]); | 62 fResults->key(FLAGS_key[i - 1], FLAGS_key[i]); |
66 } | 63 } |
67 } | 64 } |
68 | 65 |
69 if (1 == FLAGS_properties.count() % 2) { | 66 if (1 == FLAGS_properties.count() % 2) { |
70 SkDebugf("ERROR: --properties must be passed with an even number of argu
ments.\n"); | 67 SkDebugf("ERROR: --properties must be passed with an even number of argu
ments.\n"); |
71 } else { | 68 } else { |
72 for (int i = 1; i < FLAGS_properties.count(); i += 2) { | 69 for (int i = 1; i < FLAGS_properties.count(); i += 2) { |
73 fResults->property(FLAGS_properties[i - 1], FLAGS_properties[i]); | 70 fResults->property(FLAGS_properties[i - 1], FLAGS_properties[i]); |
74 } | 71 } |
75 } | 72 } |
| 73 |
| 74 // seed an initial record |
| 75 fRecords.push_back(); |
76 } | 76 } |
77 | 77 |
78 inline void VisualLightweightBenchModule::renderFrame(SkCanvas* canvas) { | 78 void VisualLightweightBenchModule::renderFrame(SkCanvas* canvas, Benchmark* benc
hmark, int loops) { |
79 fBenchmark->draw(fTSM.loops(), canvas); | 79 benchmark->draw(loops, canvas); |
80 canvas->flush(); | 80 canvas->flush(); |
81 fOwner->present(); | |
82 } | 81 } |
83 | 82 |
84 void VisualLightweightBenchModule::printStats() { | 83 void VisualLightweightBenchModule::printStats(Benchmark* benchmark, int loops) { |
85 const SkTArray<double>& measurements = fRecords.back().fMeasurements; | 84 const SkTArray<double>& measurements = fRecords.back().fMeasurements; |
86 const char* shortName = fBenchmark->getUniqueName(); | 85 const char* shortName = benchmark->getUniqueName(); |
87 | 86 |
88 // update log | 87 // update log |
89 // Note: We currently log only the minimum. It would be interesting to log
more information | 88 // Note: We currently log only the minimum. It would be interesting to log
more information |
90 SkString configName; | 89 SkString configName; |
91 if (FLAGS_msaa > 0) { | 90 if (FLAGS_msaa > 0) { |
92 configName.appendf("msaa_%d", FLAGS_msaa); | 91 configName.appendf("msaa_%d", FLAGS_msaa); |
93 } else { | 92 } else { |
94 configName.appendf("gpu"); | 93 configName.appendf("gpu"); |
95 } | 94 } |
| 95 // Log bench name |
| 96 fResults->bench(shortName, benchmark->getSize().fX, benchmark->getSize().fY)
; |
| 97 |
96 fResults->config(configName.c_str()); | 98 fResults->config(configName.c_str()); |
97 fResults->configOption("name", shortName); | 99 fResults->configOption("name", shortName); |
98 SkASSERT(measurements.count()); | 100 SkASSERT(measurements.count()); |
99 Stats stats(measurements); | 101 Stats stats(measurements); |
100 fResults->metric("min_ms", stats.min); | 102 fResults->metric("min_ms", stats.min); |
101 | 103 |
102 // Print output | 104 // Print output |
103 if (FLAGS_verbose) { | 105 if (FLAGS_verbose) { |
104 for (int i = 0; i < measurements.count(); i++) { | 106 for (int i = 0; i < measurements.count(); i++) { |
105 SkDebugf("%s ", HUMANIZE(measurements[i])); | 107 SkDebugf("%s ", HUMANIZE(measurements[i])); |
106 } | 108 } |
107 SkDebugf("%s\n", shortName); | 109 SkDebugf("%s\n", shortName); |
108 } else { | 110 } else { |
109 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean; | 111 const double stdDevPercent = 100 * sqrt(stats.var) / stats.mean; |
110 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\n", | 112 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\n", |
111 sk_tools::getCurrResidentSetSizeMB(), | 113 sk_tools::getCurrResidentSetSizeMB(), |
112 sk_tools::getMaxResidentSetSizeMB(), | 114 sk_tools::getMaxResidentSetSizeMB(), |
113 fTSM.loops(), | 115 loops, |
114 HUMANIZE(stats.min), | 116 HUMANIZE(stats.min), |
115 HUMANIZE(stats.median), | 117 HUMANIZE(stats.median), |
116 HUMANIZE(stats.mean), | 118 HUMANIZE(stats.mean), |
117 HUMANIZE(stats.max), | 119 HUMANIZE(stats.max), |
118 stdDevPercent, | 120 stdDevPercent, |
119 stats.plot.c_str(), | 121 stats.plot.c_str(), |
120 shortName); | 122 shortName); |
121 } | 123 } |
122 } | 124 } |
123 | 125 |
124 bool VisualLightweightBenchModule::advanceRecordIfNecessary(SkCanvas* canvas) { | 126 bool VisualLightweightBenchModule::timingFinished(Benchmark* benchmark, int loop
s, |
125 if (fBenchmark) { | 127 double measurement) { |
| 128 fRecords.back().fMeasurements.push_back(measurement); |
| 129 if (++fCurrentSample > FLAGS_samples) { |
| 130 this->printStats(benchmark, loops); |
| 131 fRecords.push_back(); |
| 132 fCurrentSample = 0; |
126 return true; | 133 return true; |
127 } | 134 } |
128 | 135 return false; |
129 fBenchmark.reset(fBenchmarkStream->next()); | |
130 if (!fBenchmark) { | |
131 return false; | |
132 } | |
133 | |
134 fOwner->clear(canvas, SK_ColorWHITE, 2); | |
135 | |
136 fRecords.push_back(); | |
137 | |
138 // Log bench name | |
139 fResults->bench(fBenchmark->getUniqueName(), fBenchmark->getSize().fX, | |
140 fBenchmark->getSize().fY); | |
141 | |
142 fBenchmark->delayedSetup(); | |
143 fBenchmark->preTimingHooks(canvas); | |
144 return true; | |
145 } | |
146 | |
147 void VisualLightweightBenchModule::draw(SkCanvas* canvas) { | |
148 if (!this->advanceRecordIfNecessary(canvas)) { | |
149 SkDebugf("Exiting VisualBench successfully\n"); | |
150 fOwner->closeWindow(); | |
151 return; | |
152 } | |
153 | |
154 if (fHasBeenReset) { | |
155 fHasBeenReset = false; | |
156 fBenchmark->preTimingHooks(canvas); | |
157 } | |
158 | |
159 this->renderFrame(canvas); | |
160 TimingStateMachine::ParentEvents event = fTSM.nextFrame(true); | |
161 switch (event) { | |
162 case TimingStateMachine::kReset_ParentEvents: | |
163 fBenchmark->postTimingHooks(canvas); | |
164 fOwner->reset(); | |
165 fHasBeenReset = true; | |
166 break; | |
167 case TimingStateMachine::kTiming_ParentEvents: | |
168 break; | |
169 case TimingStateMachine::kTimingFinished_ParentEvents: | |
170 fBenchmark->postTimingHooks(canvas); | |
171 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); | |
178 } else { | |
179 fHasBeenReset = true; | |
180 } | |
181 break; | |
182 } | |
183 } | 136 } |
184 | 137 |
185 bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) { | 138 bool VisualLightweightBenchModule::onHandleChar(SkUnichar c) { |
186 return true; | 139 return true; |
187 } | 140 } |
OLD | NEW |