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