Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 * Classes for writing out bench results in various formats. | 7 * Classes for writing out bench results in various formats. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 #ifndef SkPictureResultsWriter_DEFINED | 10 #ifndef SkPictureResultsWriter_DEFINED |
| 11 #define SkPictureResultsWriter_DEFINED | 11 #define SkPictureResultsWriter_DEFINED |
| 12 | 12 |
| 13 | |
| 14 #include "PictureRenderer.h" | |
| 13 #include "BenchLogger.h" | 15 #include "BenchLogger.h" |
| 14 #include "ResultsWriter.h" | 16 #include "ResultsWriter.h" |
| 15 #include "SkJSONCPP.h" | 17 #include "SkJSONCPP.h" |
| 16 #include "SkStream.h" | 18 #include "SkStream.h" |
| 17 #include "SkString.h" | 19 #include "SkString.h" |
| 18 #include "SkTArray.h" | 20 #include "SkTArray.h" |
| 19 #include "TimerData.h" | 21 #include "TimerData.h" |
| 20 | 22 |
| 23 using namespace sk_tools; | |
|
jcgregorio
2014/06/23 19:02:44
I'm leery of blanket using statements like this, d
kelvinly
2014/06/23 20:32:46
Done.
| |
| 24 | |
| 21 /** | 25 /** |
| 22 * Base class for writing picture bench results. | 26 * Base class for writing picture bench results. |
| 23 */ | 27 */ |
| 24 class PictureResultsWriter : SkNoncopyable { | 28 class PictureResultsWriter : SkNoncopyable { |
| 25 public: | 29 public: |
| 26 enum TileFlags {kPurging, kAvg}; | 30 enum TileFlags {kPurging, kAvg}; |
| 27 | 31 |
| 28 PictureResultsWriter() {} | 32 PictureResultsWriter() {} |
| 29 virtual ~PictureResultsWriter() {} | 33 virtual ~PictureResultsWriter() {} |
| 30 | 34 |
| 31 virtual void bench(const char name[], int32_t x, int32_t y) = 0; | 35 virtual void bench(const char name[], int32_t x, int32_t y) = 0; |
| 32 virtual void tileConfig(SkString configName) = 0; | 36 virtual void logRenderer(PictureRenderer *pr) = 0; |
| 33 virtual void tileMeta(int x, int y, int tx, int ty) = 0; | 37 virtual void tileMeta(int x, int y, int tx, int ty) = 0; |
| 34 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; | 38 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; |
| 35 virtual void tileData( | 39 virtual void tileData( |
| 36 TimerData* data, | 40 TimerData* data, |
| 37 const char format[], | 41 const char format[], |
| 38 const TimerData::Result result, | 42 const TimerData::Result result, |
| 39 uint32_t timerTypes, | 43 uint32_t timerTypes, |
| 40 int numInnerLoops = 1) = 0; | 44 int numInnerLoops = 1) = 0; |
| 41 virtual void end() = 0; | 45 virtual void end() = 0; |
| 42 }; | 46 }; |
| 43 | 47 |
| 44 /** | 48 /** |
| 45 * This class allows bench data to be piped into multiple | 49 * This class allows bench data to be piped into multiple |
| 46 * PictureResultWriter classes. It does not own any classes | 50 * PictureResultWriter classes. It does not own any classes |
| 47 * passed to it, so the owner is required to manage any classes | 51 * passed to it, so the owner is required to manage any classes |
| 48 * passed to PictureResultsMultiWriter */ | 52 * passed to PictureResultsMultiWriter */ |
| 49 class PictureResultsMultiWriter : public PictureResultsWriter { | 53 class PictureResultsMultiWriter : public PictureResultsWriter { |
| 50 public: | 54 public: |
| 51 PictureResultsMultiWriter() | 55 PictureResultsMultiWriter() |
| 52 : fWriters() {} | 56 : fWriters() {} |
| 53 void add(PictureResultsWriter* newWriter) { | 57 void add(PictureResultsWriter* newWriter) { |
| 54 fWriters.push_back(newWriter); | 58 fWriters.push_back(newWriter); |
| 55 } | 59 } |
| 56 virtual ~PictureResultsMultiWriter() {} | 60 virtual ~PictureResultsMultiWriter() {} |
| 57 virtual void bench(const char name[], int32_t x, int32_t y) { | 61 virtual void bench(const char name[], int32_t x, int32_t y) { |
| 58 for(int i=0; i<fWriters.count(); ++i) { | 62 for(int i=0; i<fWriters.count(); ++i) { |
| 59 fWriters[i]->bench(name, x, y); | 63 fWriters[i]->bench(name, x, y); |
| 60 } | 64 } |
| 61 } | 65 } |
| 62 virtual void tileConfig(SkString configName) { | 66 virtual void logRenderer(PictureRenderer *pr) { |
| 63 for(int i=0; i<fWriters.count(); ++i) { | 67 for(int i=0; i<fWriters.count(); ++i) { |
| 64 fWriters[i]->tileConfig(configName); | 68 fWriters[i]->logRenderer(pr); |
| 65 } | 69 } |
| 66 } | 70 } |
| 67 virtual void tileMeta(int x, int y, int tx, int ty) { | 71 virtual void tileMeta(int x, int y, int tx, int ty) { |
| 68 for(int i=0; i<fWriters.count(); ++i) { | 72 for(int i=0; i<fWriters.count(); ++i) { |
| 69 fWriters[i]->tileMeta(x, y, tx, ty); | 73 fWriters[i]->tileMeta(x, y, tx, ty); |
| 70 } | 74 } |
| 71 } | 75 } |
| 72 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { | 76 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { |
| 73 for(int i=0; i<fWriters.count(); ++i) { | 77 for(int i=0; i<fWriters.count(); ++i) { |
| 74 fWriters[i]->addTileFlag(flag); | 78 fWriters[i]->addTileFlag(flag); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 105 } | 109 } |
| 106 } | 110 } |
| 107 public: | 111 public: |
| 108 PictureResultsLoggerWriter(BenchLogger* log) | 112 PictureResultsLoggerWriter(BenchLogger* log) |
| 109 : fLogger(log), currentLine() {} | 113 : fLogger(log), currentLine() {} |
| 110 virtual void bench(const char name[], int32_t x, int32_t y) { | 114 virtual void bench(const char name[], int32_t x, int32_t y) { |
| 111 SkString result; | 115 SkString result; |
| 112 result.printf("running bench [%i %i] %s ", x, y, name); | 116 result.printf("running bench [%i %i] %s ", x, y, name); |
| 113 this->logProgress(result.c_str()); | 117 this->logProgress(result.c_str()); |
| 114 } | 118 } |
| 115 virtual void tileConfig(SkString configName) { | 119 virtual void logRenderer(PictureRenderer* renderer) { |
| 116 currentLine = configName; | 120 currentLine = renderer->getConfigName(); |
| 117 } | 121 } |
| 118 virtual void tileMeta(int x, int y, int tx, int ty) { | 122 virtual void tileMeta(int x, int y, int tx, int ty) { |
| 119 currentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); | 123 currentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); |
| 120 } | 124 } |
| 121 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { | 125 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { |
| 122 if(flag == PictureResultsWriter::kPurging) { | 126 if(flag == PictureResultsWriter::kPurging) { |
| 123 currentLine.append(" <withPurging>"); | 127 currentLine.append(" <withPurging>"); |
| 124 } else if(flag == PictureResultsWriter::kAvg) { | 128 } else if(flag == PictureResultsWriter::kAvg) { |
| 125 currentLine.append(" <averaged>"); | 129 currentLine.append(" <averaged>"); |
| 126 } | 130 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 * } | 169 * } |
| 166 * ] | 170 * ] |
| 167 * } | 171 * } |
| 168 * ] | 172 * ] |
| 169 * } | 173 * } |
| 170 * ] | 174 * ] |
| 171 * }*/ | 175 * }*/ |
| 172 | 176 |
| 173 class PictureJSONResultsWriter : public PictureResultsWriter { | 177 class PictureJSONResultsWriter : public PictureResultsWriter { |
| 174 public: | 178 public: |
| 175 PictureJSONResultsWriter(const char filename[]) | 179 PictureJSONResultsWriter(const char filename[], |
| 176 : fFilename(filename), | 180 const char builderName[], |
|
jcgregorio
2014/06/23 19:02:44
Align with first param decl.
kelvinly
2014/06/23 20:32:46
Done.
| |
| 177 fRoot(), | 181 int buildNumber, |
| 178 fCurrentBench(NULL), | 182 int timestamp, |
| 179 fCurrentTileSet(NULL), | 183 const char gitHash[], |
| 180 fCurrentTile(NULL) {} | 184 int gitNumber) |
| 185 : fStream(filename), | |
|
jcgregorio
2014/06/23 19:02:44
I believe this should be:
: fStream(filename)
, f
kelvinly
2014/06/23 20:32:46
Won't compile the other way
jcgregorio
2014/06/23 20:40:44
Sorry, wasn't commenting on the order, just the fo
kelvinly
2014/06/23 20:49:27
Ah, my bad, fixed
| |
| 186 fParams(), | |
| 187 fConfigString() { | |
| 188 const char keys[6][32] = { | |
|
jcgregorio
2014/06/23 19:02:44
Why not const char *keys[6] = {"role", ...
Also,
kelvinly
2014/06/23 20:32:46
Moved this to a function in ResultsWriter.cpp, to
| |
| 189 "role", "os", "model", "gpu", "arch", "configuration"}; | |
| 190 const int numKeys = 6; | |
|
jcgregorio
2014/06/23 19:02:44
Is 6 just the size of keys? I'm pretty sure we hav
kelvinly
2014/06/23 20:32:46
Um, would you happen to know it off the top of you
jcgregorio
2014/06/23 20:40:44
Good question, I usually rely on grepping the sour
| |
| 191 fBuilderName = SkString(builderName); | |
| 192 fBuildNumber = buildNumber; | |
| 193 fTimestamp = timestamp; | |
| 194 fGitHash = SkString(gitHash); | |
| 195 fGitNumber = gitNumber; | |
| 196 fBuilderData = Json::Value(); | |
| 197 | |
| 198 if(fBuilderName.size() > 0) { | |
| 199 SkTArray<SkString> splitBuilder; | |
| 200 SkStrSplit(builderName, "-", &splitBuilder); | |
| 201 for(int i = 0; i < numKeys && i < splitBuilder.count(); i++) { | |
| 202 fBuilderData[keys[i]] = splitBuilder[i].c_str(); | |
| 203 } | |
| 204 fBuilderData["builderName"] = builderName; | |
| 205 if(numKeys < splitBuilder.count()) { | |
| 206 SkString extras; | |
| 207 for(int i = numKeys; i < splitBuilder.count(); i++) { | |
| 208 extras.append(splitBuilder[i]); | |
| 209 if(i != splitBuilder.count() - 1) { | |
| 210 extras.append("-"); | |
| 211 } | |
| 212 } | |
| 213 fBuilderData["badParams"] = extras.c_str(); | |
| 214 } | |
| 215 } | |
| 216 } | |
| 181 | 217 |
| 182 virtual void bench(const char name[], int32_t x, int32_t y) { | 218 virtual void bench(const char name[], int32_t x, int32_t y) { |
| 183 SkString sk_name(name); | 219 fBenchName = SkString(name); |
| 184 sk_name.append("_"); | |
| 185 sk_name.appendS32(x); | |
| 186 sk_name.append("_"); | |
| 187 sk_name.appendS32(y); | |
| 188 Json::Value* bench_node = SkFindNamedNode(&fRoot["benches"], sk_name.c_s tr()); | |
| 189 fCurrentBench = &(*bench_node)["tileSets"]; | |
| 190 } | 220 } |
| 191 virtual void tileConfig(SkString configName) { | 221 virtual void logRenderer(PictureRenderer* pr) { |
| 192 SkASSERT(fCurrentBench != NULL); | 222 fParams = pr->getJSONConfig(); |
| 193 fCurrentTileSet = SkFindNamedNode(fCurrentBench, configName.c_str()); | 223 fConfigString = pr->getConfigName(); |
| 194 fCurrentTile = &(*fCurrentTileSet)["tiles"][0]; | |
| 195 } | 224 } |
| 196 virtual void tileMeta(int x, int y, int tx, int ty) { | 225 // Apparently tiles aren't used, so tileMeta is empty |
| 197 SkASSERT(fCurrentTileSet != NULL); | 226 virtual void tileMeta(int x, int y, int tx, int ty) { ; } |
| 198 (*fCurrentTileSet)["tx"] = tx; | 227 // Same here |
|
jcgregorio
2014/06/23 19:02:44
As the code changes "Same here" may make less sens
kelvinly
2014/06/23 20:32:46
Done.
| |
| 199 (*fCurrentTileSet)["ty"] = ty; | 228 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { ; } |
| 200 fCurrentTile = &(*fCurrentTileSet)["tiles"][x+tx*y]; | |
| 201 } | |
| 202 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { | |
| 203 SkASSERT(fCurrentTile != NULL); | |
| 204 if(flag == PictureResultsWriter::kPurging) { | |
| 205 (*fCurrentTile)["flags"]["purging"] = true; | |
| 206 } else if(flag == PictureResultsWriter::kAvg) { | |
| 207 (*fCurrentTile)["flags"]["averaged"] = true; | |
| 208 } | |
| 209 } | |
| 210 virtual void tileData( | 229 virtual void tileData( |
| 211 TimerData* data, | 230 TimerData* data, |
| 212 const char format[], | 231 const char format[], |
| 213 const TimerData::Result result, | 232 const TimerData::Result result, |
| 214 uint32_t timerTypes, | 233 uint32_t timerTypes, |
| 215 int numInnerLoops = 1) { | 234 int numInnerLoops = 1) { |
| 216 SkASSERT(fCurrentTile != NULL); | 235 Json::Value newData = data->getJSON(timerTypes, result, numInnerLoops); |
| 217 (*fCurrentTile)["data"] = data->getJSON(timerTypes, result, numInnerLoop s); | 236 Json::Value combinedParams(fBuilderData); |
| 237 for(Json::ValueIterator iter = fParams.begin(); iter != fParams.end(); | |
| 238 iter++) { | |
| 239 combinedParams[iter.key().asString()]= *iter; | |
| 240 } | |
| 241 // For each set of timer data | |
| 242 for(Json::ValueIterator iter = newData.begin(); iter != newData.end(); | |
| 243 iter++) { | |
| 244 Json::Value data; | |
| 245 data["buildNumber"] = fBuildNumber; | |
| 246 data["timestamp"] = fTimestamp; | |
| 247 data["gitHash"] = fGitHash.c_str(); | |
| 248 data["gitNumber"] = fGitNumber; | |
| 249 data["isTrybot"] = fBuilderName.endsWith("Trybot"); | |
| 250 | |
| 251 data["params"] = combinedParams; | |
| 252 data["params"]["benchName"] = fBenchName.c_str(); | |
| 253 | |
| 254 // Not including skpSize because that's deprecated? | |
| 255 data["key"] = makeKey(iter.key().asString().c_str()).c_str(); | |
| 256 // Get the data | |
| 257 SkTArray<double> times; | |
| 258 Json::Value val = *iter; | |
| 259 for(Json::ValueIterator vals = val.begin(); vals != val.end(); | |
| 260 vals++) { | |
| 261 times.push_back((*vals).asDouble()); | |
| 262 } | |
| 263 // Because there's no sort I'll just remove the smallest | |
|
jcgregorio
2014/06/23 19:02:44
qsort?
kelvinly
2014/06/23 20:32:46
Can you get the raw array out of an SkTArray?
jcgregorio
2014/06/23 20:40:44
begin()?
On 2014/06/23 20:32:46, kelvinly wrote:
kelvinly
2014/06/23 20:49:27
I don't think we have a begin(): https://code.goog
jcgregorio
2014/06/23 20:52:59
Don't reference code.google.com, that's not canoni
kelvinly
2014/06/23 21:10:48
Fixed
| |
| 264 // 25% of values | |
| 265 int numValues = times.count(); | |
| 266 double currentMin = 10000000.0f; | |
| 267 for(int i = 0; i < numValues; i++) { | |
| 268 if(times[i] < currentMin) { | |
| 269 currentMin = times[i]; | |
| 270 } | |
| 271 } | |
| 272 for(int i = 0; i < numValues*0.25f; i++) { | |
| 273 double localMin = currentMin; | |
| 274 for(int j = 0; j < numValues; j++) { | |
| 275 if(times[i] > currentMin && times[i] < localMin) { | |
| 276 localMin = times[i]; | |
| 277 } | |
| 278 } | |
| 279 currentMin = localMin; | |
| 280 } | |
| 281 data["value"] = currentMin; | |
| 282 data["params"]["measurementType"] = iter.key().asString(); | |
| 283 fStream.writeText(Json::FastWriter().write(data).c_str()); | |
| 284 } | |
| 218 } | 285 } |
| 219 virtual void end() { | 286 virtual void end() { |
| 220 SkFILEWStream stream(fFilename.c_str()); | 287 fStream.flush(); |
| 221 stream.writeText(Json::FastWriter().write(fRoot).c_str()); | |
| 222 stream.flush(); | |
| 223 } | 288 } |
| 224 private: | 289 private: |
| 225 SkString fFilename; | 290 SkString makeKey(const char measurementType[]) { |
| 226 Json::Value fRoot; | 291 SkString tmp(fBuilderName); |
| 227 Json::Value *fCurrentBench; | 292 tmp.append("_"); |
| 228 Json::Value *fCurrentTileSet; | 293 tmp.append(fBenchName); |
| 229 Json::Value *fCurrentTile; | 294 tmp.append("_"); |
| 295 tmp.append(fConfigString); | |
| 296 tmp.append("_"); | |
| 297 tmp.append(measurementType); | |
| 298 return tmp; | |
| 299 } | |
| 300 | |
| 301 SkFILEWStream fStream; | |
| 302 Json::Value fBuilderData; | |
| 303 SkString fBenchName; | |
| 304 Json::Value fParams; | |
| 305 | |
| 306 SkString fConfigString; | |
| 307 SkString fBuilderName; | |
| 308 int fBuildNumber; | |
| 309 int fTimestamp; | |
| 310 SkString fGitHash; | |
| 311 int fGitNumber; | |
| 230 }; | 312 }; |
| 231 | 313 |
| 232 #endif | 314 #endif |
| OLD | NEW |