• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PictureResultsWriter()28     PictureResultsWriter() {}
~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:
PictureResultsMultiWriter()51     PictureResultsMultiWriter()
52         : fWriters() {}
add(PictureResultsWriter * newWriter)53     void add(PictureResultsWriter* newWriter) {
54         fWriters.push_back(newWriter);
55     }
~PictureResultsMultiWriter()56     virtual ~PictureResultsMultiWriter() {}
bench(const char name[],int32_t x,int32_t y)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     }
tileConfig(SkString configName)62     virtual void tileConfig(SkString configName) {
63         for(int i=0; i<fWriters.count(); ++i) {
64             fWriters[i]->tileConfig(configName);
65         }
66     }
tileMeta(int x,int y,int tx,int ty)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     }
addTileFlag(PictureResultsWriter::TileFlags flag)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     }
end()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:
logProgress(const char str[])102     void logProgress(const char str[]) {
103         if(fLogger != NULL) {
104             fLogger->logProgress(str);
105         }
106     }
107 public:
PictureResultsLoggerWriter(BenchLogger * log)108     PictureResultsLoggerWriter(BenchLogger* log)
109           : fLogger(log), currentLine() {}
bench(const char name[],int32_t x,int32_t y)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     }
tileConfig(SkString configName)115     virtual void tileConfig(SkString configName) {
116         currentLine = configName;
117     }
tileMeta(int x,int y,int tx,int ty)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     }
addTileFlag(PictureResultsWriter::TileFlags flag)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     }
end()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:
PictureJSONResultsWriter(const char filename[])175     PictureJSONResultsWriter(const char filename[])
176         : fFilename(filename),
177           fRoot(),
178           fCurrentBench(NULL),
179           fCurrentTileSet(NULL),
180           fCurrentTile(NULL) {}
181 
bench(const char name[],int32_t x,int32_t y)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     }
tileConfig(SkString configName)191     virtual void tileConfig(SkString configName) {
192         SkASSERT(fCurrentBench != NULL);
193         fCurrentTileSet = SkFindNamedNode(fCurrentBench, configName.c_str());
194         fCurrentTile = &(*fCurrentTileSet)["tiles"][0];
195     }
tileMeta(int x,int y,int tx,int ty)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     }
addTileFlag(PictureResultsWriter::TileFlags flag)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     }
end()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