| 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 |