blob: f3b2da8409c08f6f5c208932e6d91ae0b8bff3d8 [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 */
tfarinaf168b862014-06-19 12:32:29 -07009
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000010#ifndef SkPictureResultsWriter_DEFINED
11#define SkPictureResultsWriter_DEFINED
12
kelvinly4d1a3642014-06-26 11:26:40 -070013
14#include "PictureRenderer.h"
tfarinaf168b862014-06-19 12:32:29 -070015#include "BenchLogger.h"
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000016#include "ResultsWriter.h"
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000017#include "SkJSONCPP.h"
18#include "SkStream.h"
19#include "SkString.h"
20#include "SkTArray.h"
tfarinaf168b862014-06-19 12:32:29 -070021#include "TimerData.h"
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000022
23/**
24 * Base class for writing picture bench results.
25 */
26class PictureResultsWriter : SkNoncopyable {
27public:
28 enum TileFlags {kPurging, kAvg};
29
30 PictureResultsWriter() {}
31 virtual ~PictureResultsWriter() {}
32
33 virtual void bench(const char name[], int32_t x, int32_t y) = 0;
kelvinly4d1a3642014-06-26 11:26:40 -070034 virtual void logRenderer(sk_tools::PictureRenderer *pr) = 0;
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000035 virtual void tileMeta(int x, int y, int tx, int ty) = 0;
36 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0;
37 virtual void tileData(
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +000038 TimerData* data,
39 const char format[],
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000040 const TimerData::Result result,
41 uint32_t timerTypes,
42 int numInnerLoops = 1) = 0;
43 virtual void end() = 0;
44};
45
46/**
47 * This class allows bench data to be piped into multiple
48 * PictureResultWriter classes. It does not own any classes
49 * passed to it, so the owner is required to manage any classes
50 * passed to PictureResultsMultiWriter */
51class PictureResultsMultiWriter : public PictureResultsWriter {
52public:
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +000053 PictureResultsMultiWriter()
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000054 : fWriters() {}
55 void add(PictureResultsWriter* newWriter) {
56 fWriters.push_back(newWriter);
57 }
58 virtual ~PictureResultsMultiWriter() {}
kelvinly4d1a3642014-06-26 11:26:40 -070059 virtual void bench(const char name[], int32_t x, int32_t y) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000060 for(int i=0; i<fWriters.count(); ++i) {
61 fWriters[i]->bench(name, x, y);
62 }
63 }
kelvinly4d1a3642014-06-26 11:26:40 -070064 virtual void logRenderer(sk_tools::PictureRenderer *pr) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000065 for(int i=0; i<fWriters.count(); ++i) {
kelvinly4d1a3642014-06-26 11:26:40 -070066 fWriters[i]->logRenderer(pr);
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000067 }
68 }
kelvinly4d1a3642014-06-26 11:26:40 -070069 virtual void tileMeta(int x, int y, int tx, int ty) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000070 for(int i=0; i<fWriters.count(); ++i) {
71 fWriters[i]->tileMeta(x, y, tx, ty);
72 }
73 }
kelvinly4d1a3642014-06-26 11:26:40 -070074 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000075 for(int i=0; i<fWriters.count(); ++i) {
76 fWriters[i]->addTileFlag(flag);
77 }
78 }
79 virtual void tileData(
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +000080 TimerData* data,
81 const char format[],
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000082 const TimerData::Result result,
83 uint32_t timerTypes,
kelvinly4d1a3642014-06-26 11:26:40 -070084 int numInnerLoops = 1) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000085 for(int i=0; i<fWriters.count(); ++i) {
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +000086 fWriters[i]->tileData(data, format, result, timerTypes,
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000087 numInnerLoops);
88 }
89 }
kelvinly4d1a3642014-06-26 11:26:40 -070090 virtual void end() SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +000091 for(int i=0; i<fWriters.count(); ++i) {
92 fWriters[i]->end();
93 }
94 }
95private:
96 SkTArray<PictureResultsWriter*> fWriters;
97};
98
99/**
tfarinaf168b862014-06-19 12:32:29 -0700100 * Writes to BenchLogger to mimic original behavior
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000101 */
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +0000102class PictureResultsLoggerWriter : public PictureResultsWriter {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000103private:
104 void logProgress(const char str[]) {
105 if(fLogger != NULL) {
106 fLogger->logProgress(str);
107 }
108 }
109public:
tfarinaf168b862014-06-19 12:32:29 -0700110 PictureResultsLoggerWriter(BenchLogger* log)
kelvinly4d1a3642014-06-26 11:26:40 -0700111 : fLogger(log), fCurrentLine() {}
112 virtual void bench(const char name[], int32_t x, int32_t y) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000113 SkString result;
114 result.printf("running bench [%i %i] %s ", x, y, name);
115 this->logProgress(result.c_str());
116 }
kelvinly4d1a3642014-06-26 11:26:40 -0700117 virtual void logRenderer(sk_tools::PictureRenderer* renderer) SK_OVERRIDE {
118 fCurrentLine = renderer->getConfigName();
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000119 }
kelvinly4d1a3642014-06-26 11:26:40 -0700120 virtual void tileMeta(int x, int y, int tx, int ty) SK_OVERRIDE {
121 fCurrentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty);
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000122 }
kelvinly4d1a3642014-06-26 11:26:40 -0700123 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000124 if(flag == PictureResultsWriter::kPurging) {
kelvinly4d1a3642014-06-26 11:26:40 -0700125 fCurrentLine.append(" <withPurging>");
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000126 } else if(flag == PictureResultsWriter::kAvg) {
kelvinly4d1a3642014-06-26 11:26:40 -0700127 fCurrentLine.append(" <averaged>");
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000128 }
129 }
130 virtual void tileData(
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +0000131 TimerData* data,
132 const char format[],
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000133 const TimerData::Result result,
134 uint32_t timerTypes,
kelvinly4d1a3642014-06-26 11:26:40 -0700135 int numInnerLoops = 1) SK_OVERRIDE {
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000136 SkString results = data->getResult(format, result,
kelvinly4d1a3642014-06-26 11:26:40 -0700137 fCurrentLine.c_str(), timerTypes, numInnerLoops);
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000138 results.append("\n");
139 this->logProgress(results.c_str());
140 }
141 virtual void end() {}
142private:
tfarinaf168b862014-06-19 12:32:29 -0700143 BenchLogger* fLogger;
kelvinly4d1a3642014-06-26 11:26:40 -0700144 SkString fCurrentLine;
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000145};
146
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000147/**
148 * This PictureResultsWriter collects data in a JSON node
149 *
150 * The format is something like
151 * {
152 * benches: [
153 * {
154 * name: "Name_of_test"
155 * tilesets: [
156 * {
157 * name: "Name of the configuration"
158 * tiles: [
159 * {
160 * flags: {
161 * purging: true //Flags for the current tile
162 * // are put here
163 * }
164 * data: {
165 * wsecs: [....] //Actual data ends up here
166 * }
167 * }
168 * ]
169 * }
170 * ]
171 * }
172 * ]
173 * }*/
174
175class PictureJSONResultsWriter : public PictureResultsWriter {
176public:
kelvinly4d1a3642014-06-26 11:26:40 -0700177 PictureJSONResultsWriter(const char filename[],
178 const char builderName[],
179 int buildNumber,
180 int timestamp,
181 const char gitHash[],
182 int gitNumber)
183 : fStream(filename) {
184 fBuilderName = SkString(builderName);
185 fBuildNumber = buildNumber;
186 fTimestamp = timestamp;
187 fGitHash = SkString(gitHash);
188 fGitNumber = gitNumber;
189 fBuilderData = SkMakeBuilderJSON(fBuilderName);
190 }
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000191
kelvinly4d1a3642014-06-26 11:26:40 -0700192 virtual void bench(const char name[], int32_t x, int32_t y) SK_OVERRIDE {
193 fBenchName = SkString(name);
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000194 }
kelvinly4d1a3642014-06-26 11:26:40 -0700195 virtual void logRenderer(sk_tools::PictureRenderer* pr) SK_OVERRIDE {
196 fParams = pr->getJSONConfig();
197 fConfigString = pr->getConfigName();
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000198 }
kelvinly4d1a3642014-06-26 11:26:40 -0700199 // Apparently tiles aren't used, so tileMeta is empty
200 virtual void tileMeta(int x, int y, int tx, int ty) SK_OVERRIDE {}
201 // Flags aren't used, so addTileFlag is empty
202 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) SK_OVERRIDE {}
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000203 virtual void tileData(
skia.committer@gmail.com9681eeb2014-05-30 03:06:10 +0000204 TimerData* data,
205 const char format[],
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000206 const TimerData::Result result,
207 uint32_t timerTypes,
kelvinly4d1a3642014-06-26 11:26:40 -0700208 int numInnerLoops = 1) SK_OVERRIDE {
209 Json::Value newData = data->getJSON(timerTypes, result, numInnerLoops);
210 Json::Value combinedParams(fBuilderData);
211 for(Json::ValueIterator iter = fParams.begin(); iter != fParams.end();
212 iter++) {
213 combinedParams[iter.key().asString()]= *iter;
214 }
215 // For each set of timer data
216 for(Json::ValueIterator iter = newData.begin(); iter != newData.end();
217 iter++) {
218 Json::Value data;
219 data["buildNumber"] = fBuildNumber;
220 data["timestamp"] = fTimestamp;
221 data["gitHash"] = fGitHash.c_str();
222 data["gitNumber"] = fGitNumber;
223 data["isTrybot"] = fBuilderName.endsWith("Trybot");
224
225 data["params"] = combinedParams;
226 data["params"]["benchName"] = fBenchName.c_str();
227
228 // Not including skpSize because that's deprecated?
229 data["key"] = this->makeKey(iter.key().asString().c_str()).c_str();
230 // Get the data
231 SkTArray<double> times;
232 Json::Value val = *iter;
233 for(Json::ValueIterator vals = val.begin(); vals != val.end();
234 vals++) {
235 times.push_back((*vals).asDouble());
236 }
237 qsort(static_cast<void*>(times.begin()), times.count(),
238 sizeof(double), PictureJSONResultsWriter::CompareDoubles);
239 data["value"] = times[static_cast<int>(times.count() * 0.25f)];
240 data["params"]["measurementType"] = iter.key().asString();
241 fStream.writeText(Json::FastWriter().write(data).c_str());
242 }
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000243 }
kelvinly4d1a3642014-06-26 11:26:40 -0700244 virtual void end() SK_OVERRIDE {
245 fStream.flush();
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000246 }
247private:
kelvinly4d1a3642014-06-26 11:26:40 -0700248 static int CompareDoubles(const void* p1, const void* p2) {
249 if(*static_cast<const double*>(p1) < *static_cast<const double*>(p2)) {
250 return -1;
251 } else if(*static_cast<const double*>(p1) ==
252 *static_cast<const double*>(p2)) {
253 return 0;
254 } else {
255 return 1;
256 }
257 }
258 SkString makeKey(const char measurementType[]) const {
259 SkString tmp(fBuilderName);
260 tmp.append("_");
261 tmp.append(fBenchName);
262 tmp.append("_");
263 tmp.append(fConfigString);
264 tmp.append("_");
265 tmp.append(measurementType);
266 return tmp;
267 }
268
269 SkFILEWStream fStream;
270 Json::Value fBuilderData;
271 SkString fBenchName;
272 Json::Value fParams;
273
274 SkString fConfigString;
275 SkString fBuilderName;
276 int fBuildNumber;
277 int fTimestamp;
278 SkString fGitHash;
279 int fGitNumber;
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000280};
commit-bot@chromium.org37c772a2014-05-29 17:10:24 +0000281
282#endif