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