OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2013 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 SkResultsWriter_DEFINED | |
10 #define SkResultsWriter_DEFINED | |
11 | |
12 #include "SkBenchLogger.h" | |
13 #include "SkJSONCPP.h" | |
14 #include "SkStream.h" | |
15 #include "SkString.h" | |
16 #include "SkTArray.h" | |
17 #include "SkTypes.h" | |
18 | |
19 | |
20 /** | |
21 * Base class for writing out the bench results. | |
22 * | |
23 * TODO(jcgregorio) Add info if tests fail to converge? | |
24 */ | |
25 class ResultsWriter : SkNoncopyable { | |
26 public: | |
27 virtual ~ResultsWriter() {}; | |
28 | |
29 // Records one option set for this run. All options must be set before | |
30 // calling bench(). | |
31 virtual void option(const char name[], const char value[]) = 0; | |
32 | |
33 // Denotes the start of a specific benchmark. Once bench is called, | |
34 // then config and timer can be called multiple times to record runs. | |
35 virtual void bench(const char name[], int32_t x, int32_t y) = 0; | |
36 | |
37 // Records the specific configuration a bench is run under, such as "8888". | |
38 virtual void config(const char name[]) = 0; | |
39 | |
40 // Records a single test metric. | |
41 virtual void timer(const char name[], double ms) = 0; | |
42 | |
43 // Call when all results are finished. | |
44 virtual void end() = 0; | |
45 }; | |
46 | |
47 /** | |
48 * This ResultsWriter handles writing out the human readable format of the | |
49 * bench results. | |
50 */ | |
51 class LoggerResultsWriter : public ResultsWriter { | |
52 public: | |
53 explicit LoggerResultsWriter(SkBenchLogger& logger, const char* timeFormat) | |
54 : fLogger(logger) | |
55 , fTimeFormat(timeFormat) { | |
56 fLogger.logProgress("skia bench:"); | |
57 } | |
58 virtual void option(const char name[], const char value[]) { | |
59 fLogger.logProgress(SkStringPrintf(" %s=%s", name, value)); | |
60 } | |
61 virtual void bench(const char name[], int32_t x, int32_t y) { | |
62 fLogger.logProgress(SkStringPrintf( | |
63 "\nrunning bench [%3d %3d] %40s", x, y, name)); | |
jcgregorio
2013/12/03 14:21:10
%040s produces 0-padded strings on a Mac:
http://
| |
64 } | |
65 virtual void config(const char name[]) { | |
66 fLogger.logProgress(SkStringPrintf(" %s:", name)); | |
67 } | |
68 virtual void timer(const char name[], double ms) { | |
69 fLogger.logProgress(SkStringPrintf(" %s = ", name)); | |
70 fLogger.logProgress(SkStringPrintf(fTimeFormat, ms)); | |
71 } | |
72 virtual void end() { | |
73 fLogger.logProgress("\n"); | |
74 } | |
75 private: | |
76 SkBenchLogger& fLogger; | |
77 const char* fTimeFormat; | |
78 }; | |
79 | |
80 /** | |
81 * This ResultsWriter handles writing out the results in JSON. | |
82 * | |
83 * The output looks like: | |
84 * | |
85 * { | |
86 * "options" : { | |
87 * "alpha" : "0xFF", | |
88 * "scale" : "0", | |
89 * ... | |
90 * "system" : "UNIX" | |
91 * }, | |
92 * "results" : { | |
93 * "Xfermode_Luminosity_640_480" : { | |
94 * "565" : { | |
95 * "cmsecs" : 143.188128906250, | |
96 * "msecs" : 143.835957031250 | |
97 * }, | |
98 * ... | |
99 */ | |
100 class JSONResultsWriter : public ResultsWriter { | |
101 public: | |
102 explicit JSONResultsWriter(const char filename[]) | |
103 : fFilename(filename) | |
104 , fRoot() | |
105 , fResults(fRoot["results"]) | |
106 , fBench(NULL) | |
107 , fConfig(NULL) { | |
108 } | |
109 virtual void option(const char name[], const char value[]) { | |
110 fRoot["options"][name] = value; | |
111 } | |
112 virtual void bench(const char name[], int32_t x, int32_t y) { | |
113 fBench = &fResults[SkStringPrintf( "%s_%d_%d", name, x, y).c_str()]; | |
114 } | |
115 virtual void config(const char name[]) { | |
116 SkASSERT(NULL != fBench); | |
117 fConfig = &(*fBench)[name]; | |
118 } | |
119 virtual void timer(const char name[], double ms) { | |
120 SkASSERT(NULL != fConfig); | |
121 (*fConfig)[name] = ms; | |
122 } | |
123 virtual void end() { | |
124 SkFILEWStream stream(fFilename.c_str()); | |
125 stream.writeText(fRoot.toStyledString().c_str()); | |
126 stream.flush(); | |
127 } | |
128 private: | |
129 SkString fFilename; | |
130 Json::Value fRoot; | |
131 Json::Value& fResults; | |
132 Json::Value* fBench; | |
133 Json::Value* fConfig; | |
134 }; | |
135 | |
136 /** | |
137 * This ResultsWriter writes out to multiple ResultsWriters. | |
138 */ | |
139 class MultiResultsWriter : public ResultsWriter { | |
140 public: | |
141 MultiResultsWriter() : writers() { | |
142 }; | |
143 void add(ResultsWriter* writer) { | |
144 writers.push_back(writer); | |
145 } | |
146 virtual void option(const char name[], const char value[]) { | |
147 for (int i = 0; i < writers.count(); ++i) { | |
148 writers[i]->option(name, value); | |
149 } | |
150 } | |
151 virtual void bench(const char name[], int32_t x, int32_t y) { | |
152 for (int i = 0; i < writers.count(); ++i) { | |
153 writers[i]->bench(name, x, y); | |
154 } | |
155 } | |
156 virtual void config(const char name[]) { | |
157 for (int i = 0; i < writers.count(); ++i) { | |
158 writers[i]->config(name); | |
159 } | |
160 } | |
161 virtual void timer(const char name[], double ms) { | |
162 for (int i = 0; i < writers.count(); ++i) { | |
163 writers[i]->timer(name, ms); | |
164 } | |
165 } | |
166 virtual void end() { | |
167 for (int i = 0; i < writers.count(); ++i) { | |
168 writers[i]->end(); | |
169 } | |
170 } | |
171 private: | |
172 SkTArray<ResultsWriter *> writers; | |
173 }; | |
174 | |
175 /** | |
176 * Calls the end() method of T on destruction. | |
177 */ | |
178 template <typename T> class CallEnd : SkNoncopyable { | |
179 public: | |
180 CallEnd(T& obj) : fObj(obj) {} | |
181 ~CallEnd() { fObj.end(); } | |
182 private: | |
183 T& fObj; | |
184 }; | |
185 | |
186 #endif | |
OLD | NEW |