OLD | NEW |
| (Empty) |
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 | |
14 #include "PictureRenderer.h" | |
15 #include "BenchLogger.h" | |
16 #include "ResultsWriter.h" | |
17 #include "SkJSONCPP.h" | |
18 #include "SkStream.h" | |
19 #include "SkString.h" | |
20 #include "SkTArray.h" | |
21 #include "TimerData.h" | |
22 | |
23 #include <stdlib.h> | |
24 | |
25 /** | |
26 * Base class for writing picture bench results. | |
27 */ | |
28 class PictureResultsWriter : SkNoncopyable { | |
29 public: | |
30 enum TileFlags {kPurging, kAvg}; | |
31 | |
32 PictureResultsWriter() {} | |
33 virtual ~PictureResultsWriter() {} | |
34 | |
35 virtual void bench(const char name[], int32_t x, int32_t y) = 0; | |
36 virtual void logRenderer(sk_tools::PictureRenderer *pr) = 0; | |
37 virtual void tileMeta(int x, int y, int tx, int ty) = 0; | |
38 virtual void addTileFlag(PictureResultsWriter::TileFlags flag) = 0; | |
39 virtual void tileData( | |
40 TimerData* data, | |
41 const char format[], | |
42 const TimerData::Result result, | |
43 uint32_t timerTypes, | |
44 int numInnerLoops = 1) = 0; | |
45 virtual void end() = 0; | |
46 }; | |
47 | |
48 /** | |
49 * This class allows bench data to be piped into multiple | |
50 * PictureResultWriter classes. It does not own any classes | |
51 * passed to it, so the owner is required to manage any classes | |
52 * passed to PictureResultsMultiWriter */ | |
53 class PictureResultsMultiWriter : public PictureResultsWriter { | |
54 public: | |
55 PictureResultsMultiWriter() | |
56 : fWriters() {} | |
57 void add(PictureResultsWriter* newWriter) { | |
58 fWriters.push_back(newWriter); | |
59 } | |
60 virtual ~PictureResultsMultiWriter() {} | |
61 void bench(const char name[], int32_t x, int32_t y) override { | |
62 for(int i=0; i<fWriters.count(); ++i) { | |
63 fWriters[i]->bench(name, x, y); | |
64 } | |
65 } | |
66 void logRenderer(sk_tools::PictureRenderer *pr) override { | |
67 for(int i=0; i<fWriters.count(); ++i) { | |
68 fWriters[i]->logRenderer(pr); | |
69 } | |
70 } | |
71 void tileMeta(int x, int y, int tx, int ty) override { | |
72 for(int i=0; i<fWriters.count(); ++i) { | |
73 fWriters[i]->tileMeta(x, y, tx, ty); | |
74 } | |
75 } | |
76 void addTileFlag(PictureResultsWriter::TileFlags flag) override { | |
77 for(int i=0; i<fWriters.count(); ++i) { | |
78 fWriters[i]->addTileFlag(flag); | |
79 } | |
80 } | |
81 virtual void tileData( | |
82 TimerData* data, | |
83 const char format[], | |
84 const TimerData::Result result, | |
85 uint32_t timerTypes, | |
86 int numInnerLoops = 1) override { | |
87 for(int i=0; i<fWriters.count(); ++i) { | |
88 fWriters[i]->tileData(data, format, result, timerTypes, | |
89 numInnerLoops); | |
90 } | |
91 } | |
92 void end() override { | |
93 for(int i=0; i<fWriters.count(); ++i) { | |
94 fWriters[i]->end(); | |
95 } | |
96 } | |
97 private: | |
98 SkTArray<PictureResultsWriter*> fWriters; | |
99 }; | |
100 | |
101 /** | |
102 * Writes to BenchLogger to mimic original behavior | |
103 */ | |
104 class PictureResultsLoggerWriter : public PictureResultsWriter { | |
105 private: | |
106 void logProgress(const char str[]) { | |
107 if(fLogger != nullptr) { | |
108 fLogger->logProgress(str); | |
109 } | |
110 } | |
111 public: | |
112 PictureResultsLoggerWriter(BenchLogger* log) | |
113 : fLogger(log), fCurrentLine() {} | |
114 void bench(const char name[], int32_t x, int32_t y) override { | |
115 SkString result; | |
116 result.printf("running bench [%i %i] %s ", x, y, name); | |
117 this->logProgress(result.c_str()); | |
118 } | |
119 void logRenderer(sk_tools::PictureRenderer* renderer) override { | |
120 fCurrentLine = renderer->getConfigName(); | |
121 } | |
122 void tileMeta(int x, int y, int tx, int ty) override { | |
123 fCurrentLine.appendf(": tile [%i,%i] out of [%i,%i]", x, y, tx, ty); | |
124 } | |
125 void addTileFlag(PictureResultsWriter::TileFlags flag) override { | |
126 if(flag == PictureResultsWriter::kPurging) { | |
127 fCurrentLine.append(" <withPurging>"); | |
128 } else if(flag == PictureResultsWriter::kAvg) { | |
129 fCurrentLine.append(" <averaged>"); | |
130 } | |
131 } | |
132 virtual void tileData( | |
133 TimerData* data, | |
134 const char format[], | |
135 const TimerData::Result result, | |
136 uint32_t timerTypes, | |
137 int numInnerLoops = 1) override { | |
138 SkString results = data->getResult(format, result, | |
139 fCurrentLine.c_str(), timerTypes, numInnerLoops); | |
140 results.append("\n"); | |
141 this->logProgress(results.c_str()); | |
142 } | |
143 void end() override {} | |
144 private: | |
145 BenchLogger* fLogger; | |
146 SkString fCurrentLine; | |
147 }; | |
148 | |
149 /** | |
150 * This PictureResultsWriter collects data in a JSON node | |
151 * | |
152 * The format is something like | |
153 * { | |
154 * benches: [ | |
155 * { | |
156 * name: "Name_of_test" | |
157 * tilesets: [ | |
158 * { | |
159 * name: "Name of the configuration" | |
160 * tiles: [ | |
161 * { | |
162 * flags: { | |
163 * purging: true //Flags for the current tile | |
164 * // are put here | |
165 * } | |
166 * data: { | |
167 * wsecs: [....] //Actual data ends up here | |
168 * } | |
169 * } | |
170 * ] | |
171 * } | |
172 * ] | |
173 * } | |
174 * ] | |
175 * }*/ | |
176 | |
177 class PictureJSONResultsWriter : public PictureResultsWriter { | |
178 public: | |
179 PictureJSONResultsWriter(const char filename[], | |
180 const char builderName[], | |
181 int buildNumber, | |
182 int timestamp, | |
183 const char gitHash[], | |
184 int gitNumber) | |
185 : fStream(filename) { | |
186 fBuilderName = SkString(builderName); | |
187 fBuildNumber = buildNumber; | |
188 fTimestamp = timestamp; | |
189 fGitHash = SkString(gitHash); | |
190 fGitNumber = gitNumber; | |
191 fBuilderData = this->makeBuilderJson(); | |
192 } | |
193 | |
194 void bench(const char name[], int32_t x, int32_t y) override { | |
195 fBenchName = SkString(name); | |
196 } | |
197 void logRenderer(sk_tools::PictureRenderer* pr) override { | |
198 fParams = pr->getJSONConfig(); | |
199 fConfigString = pr->getConfigName(); | |
200 } | |
201 // Apparently tiles aren't used, so tileMeta is empty | |
202 void tileMeta(int x, int y, int tx, int ty) override {} | |
203 // Flags aren't used, so addTileFlag is empty | |
204 void addTileFlag(PictureResultsWriter::TileFlags flag) override {} | |
205 virtual void tileData( | |
206 TimerData* data, | |
207 const char format[], | |
208 const TimerData::Result result, | |
209 uint32_t timerTypes, | |
210 int numInnerLoops = 1) override { | |
211 Json::Value newData = data->getJSON(timerTypes, result, numInnerLoops); | |
212 Json::Value combinedParams(fBuilderData); | |
213 for(Json::ValueIterator iter = fParams.begin(); iter != fParams.end(); | |
214 iter++) { | |
215 combinedParams[iter.key().asString()]= *iter; | |
216 } | |
217 // For each set of timer data | |
218 for(Json::ValueIterator iter = newData.begin(); iter != newData.end(); | |
219 iter++) { | |
220 Json::Value data; | |
221 data["buildNumber"] = fBuildNumber; | |
222 data["timestamp"] = fTimestamp; | |
223 data["gitHash"] = fGitHash.c_str(); | |
224 data["gitNumber"] = fGitNumber; | |
225 data["isTrybot"] = fBuilderName.endsWith("Trybot"); | |
226 | |
227 data["params"] = combinedParams; | |
228 data["params"]["benchName"] = fBenchName.c_str(); | |
229 | |
230 // Not including skpSize because that's deprecated? | |
231 data["key"] = this->makeKey(iter.key().asString().c_str()).c_str(); | |
232 // Get the data | |
233 SkTArray<double> times; | |
234 Json::Value val = *iter; | |
235 for(Json::ValueIterator vals = val.begin(); vals != val.end(); | |
236 vals++) { | |
237 times.push_back((*vals).asDouble()); | |
238 } | |
239 qsort(static_cast<void*>(times.begin()), times.count(), | |
240 sizeof(double), PictureJSONResultsWriter::CompareDoubles); | |
241 data["value"] = times[static_cast<int>(times.count() * 0.25f)]; | |
242 data["params"]["measurementType"] = iter.key().asString(); | |
243 fStream.writeText(Json::FastWriter().write(data).c_str()); | |
244 } | |
245 } | |
246 void end() override { | |
247 fStream.flush(); | |
248 } | |
249 private: | |
250 Json::Value makeBuilderJson() const { | |
251 static const int kNumKeys = 6; | |
252 static const char* kKeys[kNumKeys] = { | |
253 "role", "os", "model", "gpu", "arch", "configuration"}; | |
254 Json::Value builderData; | |
255 | |
256 if (!fBuilderName.isEmpty()) { | |
257 SkTArray<SkString> splitBuilder; | |
258 SkStrSplit(fBuilderName.c_str(), "-", &splitBuilder); | |
259 SkASSERT(splitBuilder.count() >= kNumKeys); | |
260 for (int i = 0; i < kNumKeys && i < splitBuilder.count(); ++i) { | |
261 builderData[kKeys[i]] = splitBuilder[i].c_str(); | |
262 } | |
263 builderData["builderName"] = fBuilderName.c_str(); | |
264 if (kNumKeys < splitBuilder.count()) { | |
265 SkString extras; | |
266 for (int i = kNumKeys; i < splitBuilder.count(); ++i) { | |
267 extras.append(splitBuilder[i]); | |
268 if (i != splitBuilder.count() - 1) { | |
269 extras.append("-"); | |
270 } | |
271 } | |
272 builderData["badParams"] = extras.c_str(); | |
273 } | |
274 } | |
275 return builderData; | |
276 } | |
277 | |
278 static int CompareDoubles(const void* p1, const void* p2) { | |
279 if(*static_cast<const double*>(p1) < *static_cast<const double*>(p2)) { | |
280 return -1; | |
281 } else if(*static_cast<const double*>(p1) == | |
282 *static_cast<const double*>(p2)) { | |
283 return 0; | |
284 } else { | |
285 return 1; | |
286 } | |
287 } | |
288 SkString makeKey(const char measurementType[]) const { | |
289 SkString tmp(fBuilderName); | |
290 tmp.append("_"); | |
291 tmp.append(fBenchName); | |
292 tmp.append("_"); | |
293 tmp.append(fConfigString); | |
294 tmp.append("_"); | |
295 tmp.append(measurementType); | |
296 return tmp; | |
297 } | |
298 | |
299 SkFILEWStream fStream; | |
300 Json::Value fBuilderData; | |
301 SkString fBenchName; | |
302 Json::Value fParams; | |
303 | |
304 SkString fConfigString; | |
305 SkString fBuilderName; | |
306 int fBuildNumber; | |
307 int fTimestamp; | |
308 SkString fGitHash; | |
309 int fGitNumber; | |
310 }; | |
311 | |
312 #endif | |
OLD | NEW |