commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014 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 | * Classes for writing out bench results in various formats. |
| 8 | */ |
tfarina | f168b86 | 2014-06-19 12:32:29 -0700 | [diff] [blame] | 9 | |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 10 | #ifndef SkPictureResultsWriter_DEFINED |
| 11 | #define SkPictureResultsWriter_DEFINED |
| 12 | |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 13 | |
| 14 | #include "PictureRenderer.h" |
tfarina | f168b86 | 2014-06-19 12:32:29 -0700 | [diff] [blame] | 15 | #include "BenchLogger.h" |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 16 | #include "ResultsWriter.h" |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 17 | #include "SkJSONCPP.h" |
| 18 | #include "SkStream.h" |
| 19 | #include "SkString.h" |
| 20 | #include "SkTArray.h" |
tfarina | f168b86 | 2014-06-19 12:32:29 -0700 | [diff] [blame] | 21 | #include "TimerData.h" |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 22 | |
bungeman | 60e0fee | 2015-08-26 05:15:46 -0700 | [diff] [blame] | 23 | #include <stdlib.h> |
| 24 | |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 25 | /** |
| 26 | * Base class for writing picture bench results. |
| 27 | */ |
| 28 | class PictureResultsWriter : SkNoncopyable { |
| 29 | public: |
| 30 | enum TileFlags {kPurging, kAvg}; |
| 31 | |
| 32 | PictureResultsWriter() {} |
| 33 | virtual ~PictureResultsWriter() {} |
| 34 | |
| 35 | virtual void bench(const char name[], int32_t x, int32_t y) = 0; |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 36 | virtual void logRenderer(sk_tools::PictureRenderer *pr) = 0; |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 37 | virtual void tileMeta(int x, int y, int tx, int ty) = 0; |
| 38 | virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; |
| 39 | virtual void tileData( |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 40 | TimerData* data, |
| 41 | const char format[], |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 42 | const TimerData::Result result, |
| 43 | uint32_t timerTypes, |
| 44 | int numInnerLoops = 1) = 0; |
| 45 | virtual void end() = 0; |
| 46 | }; |
| 47 | |
| 48 | /** |
| 49 | * This class allows bench data to be piped into multiple |
| 50 | * PictureResultWriter classes. It does not own any classes |
| 51 | * passed to it, so the owner is required to manage any classes |
| 52 | * passed to PictureResultsMultiWriter */ |
| 53 | class PictureResultsMultiWriter : public PictureResultsWriter { |
| 54 | public: |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 55 | PictureResultsMultiWriter() |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 56 | : fWriters() {} |
| 57 | void add(PictureResultsWriter* newWriter) { |
| 58 | fWriters.push_back(newWriter); |
| 59 | } |
| 60 | virtual ~PictureResultsMultiWriter() {} |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 61 | void bench(const char name[], int32_t x, int32_t y) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 62 | for(int i=0; i<fWriters.count(); ++i) { |
| 63 | fWriters[i]->bench(name, x, y); |
| 64 | } |
| 65 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 66 | void logRenderer(sk_tools::PictureRenderer *pr) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 67 | for(int i=0; i<fWriters.count(); ++i) { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 68 | fWriters[i]->logRenderer(pr); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 69 | } |
| 70 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 71 | void tileMeta(int x, int y, int tx, int ty) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 72 | for(int i=0; i<fWriters.count(); ++i) { |
| 73 | fWriters[i]->tileMeta(x, y, tx, ty); |
| 74 | } |
| 75 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 76 | void addTileFlag(PictureResultsWriter::TileFlags flag) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 77 | for(int i=0; i<fWriters.count(); ++i) { |
| 78 | fWriters[i]->addTileFlag(flag); |
| 79 | } |
| 80 | } |
| 81 | virtual void tileData( |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 82 | TimerData* data, |
| 83 | const char format[], |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 84 | const TimerData::Result result, |
| 85 | uint32_t timerTypes, |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 86 | int numInnerLoops = 1) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 87 | for(int i=0; i<fWriters.count(); ++i) { |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 88 | fWriters[i]->tileData(data, format, result, timerTypes, |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 89 | numInnerLoops); |
| 90 | } |
| 91 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 92 | void end() override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 93 | for(int i=0; i<fWriters.count(); ++i) { |
| 94 | fWriters[i]->end(); |
| 95 | } |
| 96 | } |
| 97 | private: |
| 98 | SkTArray<PictureResultsWriter*> fWriters; |
| 99 | }; |
| 100 | |
| 101 | /** |
tfarina | f168b86 | 2014-06-19 12:32:29 -0700 | [diff] [blame] | 102 | * Writes to BenchLogger to mimic original behavior |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 103 | */ |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 104 | class PictureResultsLoggerWriter : public PictureResultsWriter { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 105 | private: |
| 106 | void logProgress(const char str[]) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 107 | if(fLogger != nullptr) { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 108 | fLogger->logProgress(str); |
| 109 | } |
| 110 | } |
| 111 | public: |
tfarina | f168b86 | 2014-06-19 12:32:29 -0700 | [diff] [blame] | 112 | PictureResultsLoggerWriter(BenchLogger* log) |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 113 | : fLogger(log), fCurrentLine() {} |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 114 | void bench(const char name[], int32_t x, int32_t y) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 115 | SkString result; |
| 116 | result.printf("running bench [%i %i] %s ", x, y, name); |
| 117 | this->logProgress(result.c_str()); |
| 118 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 119 | void logRenderer(sk_tools::PictureRenderer* renderer) override { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 120 | fCurrentLine = renderer->getConfigName(); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 121 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 122 | void tileMeta(int x, int y, int tx, int ty) override { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 123 | fCurrentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 124 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 125 | void addTileFlag(PictureResultsWriter::TileFlags flag) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 126 | if(flag == PictureResultsWriter::kPurging) { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 127 | fCurrentLine.append(" <withPurging>"); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 128 | } else if(flag == PictureResultsWriter::kAvg) { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 129 | fCurrentLine.append(" <averaged>"); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 130 | } |
| 131 | } |
| 132 | virtual void tileData( |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 133 | TimerData* data, |
| 134 | const char format[], |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 135 | const TimerData::Result result, |
| 136 | uint32_t timerTypes, |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 137 | int numInnerLoops = 1) override { |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 138 | SkString results = data->getResult(format, result, |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 139 | fCurrentLine.c_str(), timerTypes, numInnerLoops); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 140 | results.append("\n"); |
| 141 | this->logProgress(results.c_str()); |
| 142 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 143 | void end() override {} |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 144 | private: |
tfarina | f168b86 | 2014-06-19 12:32:29 -0700 | [diff] [blame] | 145 | BenchLogger* fLogger; |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 146 | SkString fCurrentLine; |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 147 | }; |
| 148 | |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 149 | /** |
| 150 | * This PictureResultsWriter collects data in a JSON node |
| 151 | * |
| 152 | * The format is something like |
| 153 | * { |
| 154 | * benches: [ |
| 155 | * { |
| 156 | * name: "Name_of_test" |
| 157 | * tilesets: [ |
| 158 | * { |
| 159 | * name: "Name of the configuration" |
| 160 | * tiles: [ |
| 161 | * { |
| 162 | * flags: { |
| 163 | * purging: true //Flags for the current tile |
| 164 | * // are put here |
| 165 | * } |
| 166 | * data: { |
| 167 | * wsecs: [....] //Actual data ends up here |
| 168 | * } |
| 169 | * } |
| 170 | * ] |
| 171 | * } |
| 172 | * ] |
| 173 | * } |
| 174 | * ] |
| 175 | * }*/ |
| 176 | |
| 177 | class PictureJSONResultsWriter : public PictureResultsWriter { |
| 178 | public: |
mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 179 | PictureJSONResultsWriter(const char filename[], |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 180 | const char builderName[], |
| 181 | int buildNumber, |
| 182 | int timestamp, |
| 183 | const char gitHash[], |
| 184 | int gitNumber) |
| 185 | : fStream(filename) { |
| 186 | fBuilderName = SkString(builderName); |
| 187 | fBuildNumber = buildNumber; |
| 188 | fTimestamp = timestamp; |
| 189 | fGitHash = SkString(gitHash); |
| 190 | fGitNumber = gitNumber; |
mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 191 | fBuilderData = this->makeBuilderJson(); |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 192 | } |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 193 | |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 194 | void bench(const char name[], int32_t x, int32_t y) override { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 195 | fBenchName = SkString(name); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 196 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 197 | void logRenderer(sk_tools::PictureRenderer* pr) override { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 198 | fParams = pr->getJSONConfig(); |
| 199 | fConfigString = pr->getConfigName(); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 200 | } |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 201 | // Apparently tiles aren't used, so tileMeta is empty |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 202 | void tileMeta(int x, int y, int tx, int ty) override {} |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 203 | // Flags aren't used, so addTileFlag is empty |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 204 | void addTileFlag(PictureResultsWriter::TileFlags flag) override {} |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 205 | virtual void tileData( |
skia.committer@gmail.com | 9681eeb | 2014-05-30 03:06:10 +0000 | [diff] [blame] | 206 | TimerData* data, |
| 207 | const char format[], |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 208 | const TimerData::Result result, |
| 209 | uint32_t timerTypes, |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 210 | int numInnerLoops = 1) override { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 211 | Json::Value newData = data->getJSON(timerTypes, result, numInnerLoops); |
| 212 | Json::Value combinedParams(fBuilderData); |
| 213 | for(Json::ValueIterator iter = fParams.begin(); iter != fParams.end(); |
| 214 | iter++) { |
| 215 | combinedParams[iter.key().asString()]= *iter; |
| 216 | } |
| 217 | // For each set of timer data |
| 218 | for(Json::ValueIterator iter = newData.begin(); iter != newData.end(); |
| 219 | iter++) { |
| 220 | Json::Value data; |
| 221 | data["buildNumber"] = fBuildNumber; |
| 222 | data["timestamp"] = fTimestamp; |
| 223 | data["gitHash"] = fGitHash.c_str(); |
| 224 | data["gitNumber"] = fGitNumber; |
| 225 | data["isTrybot"] = fBuilderName.endsWith("Trybot"); |
| 226 | |
| 227 | data["params"] = combinedParams; |
| 228 | data["params"]["benchName"] = fBenchName.c_str(); |
| 229 | |
| 230 | // Not including skpSize because that's deprecated? |
| 231 | data["key"] = this->makeKey(iter.key().asString().c_str()).c_str(); |
| 232 | // Get the data |
| 233 | SkTArray<double> times; |
| 234 | Json::Value val = *iter; |
| 235 | for(Json::ValueIterator vals = val.begin(); vals != val.end(); |
| 236 | vals++) { |
| 237 | times.push_back((*vals).asDouble()); |
| 238 | } |
mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 239 | qsort(static_cast<void*>(times.begin()), times.count(), |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 240 | sizeof(double), PictureJSONResultsWriter::CompareDoubles); |
| 241 | data["value"] = times[static_cast<int>(times.count() * 0.25f)]; |
| 242 | data["params"]["measurementType"] = iter.key().asString(); |
| 243 | fStream.writeText(Json::FastWriter().write(data).c_str()); |
| 244 | } |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 245 | } |
mtklein | 36352bf | 2015-03-25 18:17:31 -0700 | [diff] [blame] | 246 | void end() override { |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 247 | fStream.flush(); |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 248 | } |
| 249 | private: |
mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 250 | Json::Value makeBuilderJson() const { |
| 251 | static const int kNumKeys = 6; |
| 252 | static const char* kKeys[kNumKeys] = { |
| 253 | "role", "os", "model", "gpu", "arch", "configuration"}; |
| 254 | Json::Value builderData; |
| 255 | |
| 256 | if (!fBuilderName.isEmpty()) { |
| 257 | SkTArray<SkString> splitBuilder; |
| 258 | SkStrSplit(fBuilderName.c_str(), "-", &splitBuilder); |
| 259 | SkASSERT(splitBuilder.count() >= kNumKeys); |
| 260 | for (int i = 0; i < kNumKeys && i < splitBuilder.count(); ++i) { |
| 261 | builderData[kKeys[i]] = splitBuilder[i].c_str(); |
| 262 | } |
| 263 | builderData["builderName"] = fBuilderName.c_str(); |
| 264 | if (kNumKeys < splitBuilder.count()) { |
| 265 | SkString extras; |
| 266 | for (int i = kNumKeys; i < splitBuilder.count(); ++i) { |
| 267 | extras.append(splitBuilder[i]); |
| 268 | if (i != splitBuilder.count() - 1) { |
| 269 | extras.append("-"); |
| 270 | } |
| 271 | } |
| 272 | builderData["badParams"] = extras.c_str(); |
| 273 | } |
| 274 | } |
| 275 | return builderData; |
| 276 | } |
| 277 | |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 278 | static int CompareDoubles(const void* p1, const void* p2) { |
| 279 | if(*static_cast<const double*>(p1) < *static_cast<const double*>(p2)) { |
| 280 | return -1; |
mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 281 | } else if(*static_cast<const double*>(p1) == |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 282 | *static_cast<const double*>(p2)) { |
mtklein | 1915b62 | 2014-08-20 11:45:00 -0700 | [diff] [blame] | 283 | return 0; |
kelvinly | 4d1a364 | 2014-06-26 11:26:40 -0700 | [diff] [blame] | 284 | } else { |
| 285 | return 1; |
| 286 | } |
| 287 | } |
| 288 | SkString makeKey(const char measurementType[]) const { |
| 289 | SkString tmp(fBuilderName); |
| 290 | tmp.append("_"); |
| 291 | tmp.append(fBenchName); |
| 292 | tmp.append("_"); |
| 293 | tmp.append(fConfigString); |
| 294 | tmp.append("_"); |
| 295 | tmp.append(measurementType); |
| 296 | return tmp; |
| 297 | } |
| 298 | |
| 299 | SkFILEWStream fStream; |
| 300 | Json::Value fBuilderData; |
| 301 | SkString fBenchName; |
| 302 | Json::Value fParams; |
| 303 | |
| 304 | SkString fConfigString; |
| 305 | SkString fBuilderName; |
| 306 | int fBuildNumber; |
| 307 | int fTimestamp; |
| 308 | SkString fGitHash; |
| 309 | int fGitNumber; |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 310 | }; |
commit-bot@chromium.org | 37c772a | 2014-05-29 17:10:24 +0000 | [diff] [blame] | 311 | |
| 312 | #endif |