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