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 #include "BenchLogger.h" 14 #include "ResultsWriter.h" 15 #include "SkJSONCPP.h" 16 #include "SkStream.h" 17 #include "SkString.h" 18 #include "SkTArray.h" 19 #include "TimerData.h" 20 21 /** 22 * Base class for writing picture bench results. 23 */ 24 class PictureResultsWriter : SkNoncopyable { 25 public: 26 enum TileFlags {kPurging, kAvg}; 27 28 PictureResultsWriter() {} 29 virtual ~PictureResultsWriter() {} 30 31 virtual void bench(const char name[], int32_t x, int32_t y) = 0; 32 virtual void tileConfig(SkString configName) = 0; 33 virtual void tileMeta(int x, int y, int tx, int ty) = 0; 34 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; 35 virtual void tileData( 36 TimerData* data, 37 const char format[], 38 const TimerData::Result result, 39 uint32_t timerTypes, 40 int numInnerLoops = 1) = 0; 41 virtual void end() = 0; 42 }; 43 44 /** 45 * This class allows bench data to be piped into multiple 46 * PictureResultWriter classes. It does not own any classes 47 * passed to it, so the owner is required to manage any classes 48 * passed to PictureResultsMultiWriter */ 49 class PictureResultsMultiWriter : public PictureResultsWriter { 50 public: 51 PictureResultsMultiWriter() 52 : fWriters() {} 53 void add(PictureResultsWriter* newWriter) { 54 fWriters.push_back(newWriter); 55 } 56 virtual ~PictureResultsMultiWriter() {} 57 virtual void bench(const char name[], int32_t x, int32_t y) { 58 for(int i=0; i<fWriters.count(); ++i) { 59 fWriters[i]->bench(name, x, y); 60 } 61 } 62 virtual void tileConfig(SkString configName) { 63 for(int i=0; i<fWriters.count(); ++i) { 64 fWriters[i]->tileConfig(configName); 65 } 66 } 67 virtual void tileMeta(int x, int y, int tx, int ty) { 68 for(int i=0; i<fWriters.count(); ++i) { 69 fWriters[i]->tileMeta(x, y, tx, ty); 70 } 71 } 72 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { 73 for(int i=0; i<fWriters.count(); ++i) { 74 fWriters[i]->addTileFlag(flag); 75 } 76 } 77 virtual void tileData( 78 TimerData* data, 79 const char format[], 80 const TimerData::Result result, 81 uint32_t timerTypes, 82 int numInnerLoops = 1) { 83 for(int i=0; i<fWriters.count(); ++i) { 84 fWriters[i]->tileData(data, format, result, timerTypes, 85 numInnerLoops); 86 } 87 } 88 virtual void end() { 89 for(int i=0; i<fWriters.count(); ++i) { 90 fWriters[i]->end(); 91 } 92 } 93 private: 94 SkTArray<PictureResultsWriter*> fWriters; 95 }; 96 97 /** 98 * Writes to BenchLogger to mimic original behavior 99 */ 100 class PictureResultsLoggerWriter : public PictureResultsWriter { 101 private: 102 void logProgress(const char str[]) { 103 if(fLogger != NULL) { 104 fLogger->logProgress(str); 105 } 106 } 107 public: 108 PictureResultsLoggerWriter(BenchLogger* log) 109 : fLogger(log), currentLine() {} 110 virtual void bench(const char name[], int32_t x, int32_t y) { 111 SkString result; 112 result.printf("running bench [%i %i] %s ", x, y, name); 113 this->logProgress(result.c_str()); 114 } 115 virtual void tileConfig(SkString configName) { 116 currentLine = configName; 117 } 118 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); 120 } 121 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) { 122 if(flag == PictureResultsWriter::kPurging) { 123 currentLine.append(" <withPurging>"); 124 } else if(flag == PictureResultsWriter::kAvg) { 125 currentLine.append(" <averaged>"); 126 } 127 } 128 virtual void tileData( 129 TimerData* data, 130 const char format[], 131 const TimerData::Result result, 132 uint32_t timerTypes, 133 int numInnerLoops = 1) { 134 SkString results = data->getResult(format, result, 135 currentLine.c_str(), timerTypes, numInnerLoops); 136 results.append("\n"); 137 this->logProgress(results.c_str()); 138 } 139 virtual void end() {} 140 private: 141 BenchLogger* fLogger; 142 SkString currentLine; 143 }; 144 145 /** 146 * This PictureResultsWriter collects data in a JSON node 147 * 148 * The format is something like 149 * { 150 * benches: [ 151 * { 152 * name: "Name_of_test" 153 * tilesets: [ 154 * { 155 * name: "Name of the configuration" 156 * tiles: [ 157 * { 158 * flags: { 159 * purging: true //Flags for the current tile 160 * // are put here 161 * } 162 * data: { 163 * wsecs: [....] //Actual data ends up here 164 * } 165 * } 166 * ] 167 * } 168 * ] 169 * } 170 * ] 171 * }*/ 172 173 class PictureJSONResultsWriter : public PictureResultsWriter { 174 public: 175 PictureJSONResultsWriter(const char filename[]) 176 : fFilename(filename), 177 fRoot(), 178 fCurrentBench(NULL), 179 fCurrentTileSet(NULL), 180 fCurrentTile(NULL) {} 181 182 virtual void bench(const char name[], int32_t x, int32_t y) { 183 SkString sk_name(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_str()); 189 fCurrentBench = &(*bench_node)["tileSets"]; 190 } 191 virtual void tileConfig(SkString configName) { 192 SkASSERT(fCurrentBench != NULL); 193 fCurrentTileSet = SkFindNamedNode(fCurrentBench, configName.c_str()); 194 fCurrentTile = &(*fCurrentTileSet)["tiles"][0]; 195 } 196 virtual void tileMeta(int x, int y, int tx, int ty) { 197 SkASSERT(fCurrentTileSet != NULL); 198 (*fCurrentTileSet)["tx"] = tx; 199 (*fCurrentTileSet)["ty"] = ty; 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( 211 TimerData* data, 212 const char format[], 213 const TimerData::Result result, 214 uint32_t timerTypes, 215 int numInnerLoops = 1) { 216 SkASSERT(fCurrentTile != NULL); 217 (*fCurrentTile)["data"] = data->getJSON(timerTypes, result, numInnerLoops); 218 } 219 virtual void end() { 220 SkFILEWStream stream(fFilename.c_str()); 221 stream.writeText(Json::FastWriter().write(fRoot).c_str()); 222 stream.flush(); 223 } 224 private: 225 SkString fFilename; 226 Json::Value fRoot; 227 Json::Value *fCurrentBench; 228 Json::Value *fCurrentTileSet; 229 Json::Value *fCurrentTile; 230 }; 231 232 #endif 233