| OLD | NEW |
| (Empty) |
| 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 */ | |
| 9 | |
| 10 #ifndef SkPictureResultsWriter_DEFINED | |
| 11 #define SkPictureResultsWriter_DEFINED | |
| 12 | |
| 13 | |
| 14 #include "PictureRenderer.h" | |
| 15 #include "BenchLogger.h" | |
| 16 #include "ResultsWriter.h" | |
| 17 #include "SkJSONCPP.h" | |
| 18 #include "SkStream.h" | |
| 19 #include "SkString.h" | |
| 20 #include "SkTArray.h" | |
| 21 #include "TimerData.h" | |
| 22 | |
| 23 #include <stdlib.h> | |
| 24 | |
| 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; | |
| 36 virtual void logRenderer(sk_tools::PictureRenderer *pr) = 0; | |
| 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( | |
| 40 TimerData* data, | |
| 41 const char format[], | |
| 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: | |
| 55 PictureResultsMultiWriter() | |
| 56 : fWriters() {} | |
| 57 void add(PictureResultsWriter* newWriter) { | |
| 58 fWriters.push_back(newWriter); | |
| 59 } | |
| 60 virtual ~PictureResultsMultiWriter() {} | |
| 61 void bench(const char name[], int32_t x, int32_t y) override { | |
| 62 for(int i=0; i<fWriters.count(); ++i) { | |
| 63 fWriters[i]->bench(name, x, y); | |
| 64 } | |
| 65 } | |
| 66 void logRenderer(sk_tools::PictureRenderer *pr) override { | |
| 67 for(int i=0; i<fWriters.count(); ++i) { | |
| 68 fWriters[i]->logRenderer(pr); | |
| 69 } | |
| 70 } | |
| 71 void tileMeta(int x, int y, int tx, int ty) override { | |
| 72 for(int i=0; i<fWriters.count(); ++i) { | |
| 73 fWriters[i]->tileMeta(x, y, tx, ty); | |
| 74 } | |
| 75 } | |
| 76 void addTileFlag(PictureResultsWriter::TileFlags flag) override { | |
| 77 for(int i=0; i<fWriters.count(); ++i) { | |
| 78 fWriters[i]->addTileFlag(flag); | |
| 79 } | |
| 80 } | |
| 81 virtual void tileData( | |
| 82 TimerData* data, | |
| 83 const char format[], | |
| 84 const TimerData::Result result, | |
| 85 uint32_t timerTypes, | |
| 86 int numInnerLoops = 1) override { | |
| 87 for(int i=0; i<fWriters.count(); ++i) { | |
| 88 fWriters[i]->tileData(data, format, result, timerTypes, | |
| 89 numInnerLoops); | |
| 90 } | |
| 91 } | |
| 92 void end() override { | |
| 93 for(int i=0; i<fWriters.count(); ++i) { | |
| 94 fWriters[i]->end(); | |
| 95 } | |
| 96 } | |
| 97 private: | |
| 98 SkTArray<PictureResultsWriter*> fWriters; | |
| 99 }; | |
| 100 | |
| 101 /** | |
| 102 * Writes to BenchLogger to mimic original behavior | |
| 103 */ | |
| 104 class PictureResultsLoggerWriter : public PictureResultsWriter { | |
| 105 private: | |
| 106 void logProgress(const char str[]) { | |
| 107 if(fLogger != nullptr) { | |
| 108 fLogger->logProgress(str); | |
| 109 } | |
| 110 } | |
| 111 public: | |
| 112 PictureResultsLoggerWriter(BenchLogger* log) | |
| 113 : fLogger(log), fCurrentLine() {} | |
| 114 void bench(const char name[], int32_t x, int32_t y) override { | |
| 115 SkString result; | |
| 116 result.printf("running bench [%i %i] %s ", x, y, name); | |
| 117 this->logProgress(result.c_str()); | |
| 118 } | |
| 119 void logRenderer(sk_tools::PictureRenderer* renderer) override { | |
| 120 fCurrentLine = renderer->getConfigName(); | |
| 121 } | |
| 122 void tileMeta(int x, int y, int tx, int ty) override { | |
| 123 fCurrentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); | |
| 124 } | |
| 125 void addTileFlag(PictureResultsWriter::TileFlags flag) override { | |
| 126 if(flag == PictureResultsWriter::kPurging) { | |
| 127 fCurrentLine.append(" <withPurging>"); | |
| 128 } else if(flag == PictureResultsWriter::kAvg) { | |
| 129 fCurrentLine.append(" <averaged>"); | |
| 130 } | |
| 131 } | |
| 132 virtual void tileData( | |
| 133 TimerData* data, | |
| 134 const char format[], | |
| 135 const TimerData::Result result, | |
| 136 uint32_t timerTypes, | |
| 137 int numInnerLoops = 1) override { | |
| 138 SkString results = data->getResult(format, result, | |
| 139 fCurrentLine.c_str(), timerTypes, numInnerLoops); | |
| 140 results.append("\n"); | |
| 141 this->logProgress(results.c_str()); | |
| 142 } | |
| 143 void end() override {} | |
| 144 private: | |
| 145 BenchLogger* fLogger; | |
| 146 SkString fCurrentLine; | |
| 147 }; | |
| 148 | |
| 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: | |
| 179 PictureJSONResultsWriter(const char filename[], | |
| 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; | |
| 191 fBuilderData = this->makeBuilderJson(); | |
| 192 } | |
| 193 | |
| 194 void bench(const char name[], int32_t x, int32_t y) override { | |
| 195 fBenchName = SkString(name); | |
| 196 } | |
| 197 void logRenderer(sk_tools::PictureRenderer* pr) override { | |
| 198 fParams = pr->getJSONConfig(); | |
| 199 fConfigString = pr->getConfigName(); | |
| 200 } | |
| 201 // Apparently tiles aren't used, so tileMeta is empty | |
| 202 void tileMeta(int x, int y, int tx, int ty) override {} | |
| 203 // Flags aren't used, so addTileFlag is empty | |
| 204 void addTileFlag(PictureResultsWriter::TileFlags flag) override {} | |
| 205 virtual void tileData( | |
| 206 TimerData* data, | |
| 207 const char format[], | |
| 208 const TimerData::Result result, | |
| 209 uint32_t timerTypes, | |
| 210 int numInnerLoops = 1) override { | |
| 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 } | |
| 239 qsort(static_cast<void*>(times.begin()), times.count(), | |
| 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 } | |
| 245 } | |
| 246 void end() override { | |
| 247 fStream.flush(); | |
| 248 } | |
| 249 private: | |
| 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 | |
| 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; | |
| 281 } else if(*static_cast<const double*>(p1) == | |
| 282 *static_cast<const double*>(p2)) { | |
| 283 return 0; | |
| 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; | |
| 310 }; | |
| 311 | |
| 312 #endif | |
| OLD | NEW |