2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
7 * Classes for writing out bench results in various formats.
10 #ifndef SkResultsWriter_DEFINED
11 #define SkResultsWriter_DEFINED
13 #include "BenchLogger.h"
14 #include "SkJSONCPP.h"
21 * Base class for writing out the bench results.
23 * TODO(jcgregorio) Add info if tests fail to converge?
25 class ResultsWriter : SkNoncopyable {
27 virtual ~ResultsWriter() {};
29 // Records one option set for this run. All options must be set before
31 virtual void option(const char name[], const char value[]) = 0;
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;
37 // Records the specific configuration a bench is run under, such as "8888".
38 virtual void config(const char name[]) = 0;
40 // Records a single test metric.
41 virtual void timer(const char name[], double ms) = 0;
43 // Call when all results are finished.
44 virtual void end() = 0;
48 * This ResultsWriter handles writing out the human readable format of the
51 class LoggerResultsWriter : public ResultsWriter {
53 explicit LoggerResultsWriter(BenchLogger& logger, const char* timeFormat)
55 , fTimeFormat(timeFormat) {
56 fLogger.logProgress("skia bench:");
58 virtual void option(const char name[], const char value[]) {
59 fLogger.logProgress(SkStringPrintf(" %s=%s", name, value));
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));
65 virtual void config(const char name[]) {
66 fLogger.logProgress(SkStringPrintf(" %s:", name));
68 virtual void timer(const char name[], double ms) {
69 fLogger.logProgress(SkStringPrintf(" %s = ", name));
70 fLogger.logProgress(SkStringPrintf(fTimeFormat, ms));
73 fLogger.logProgress("\n");
77 const char* fTimeFormat;
81 * This ResultsWriter handles writing out the results in JSON.
83 * The output looks like (except compressed to a single line):
94 * "name" : "Xfermode_Luminosity_640_480",
98 * "cmsecs" : 143.188128906250,
99 * "msecs" : 143.835957031250
104 Json::Value* SkFindNamedNode(Json::Value* root, const char name[]);
105 Json::Value SkMakeBuilderJSON(const SkString &buildername);
107 class JSONResultsWriter : public ResultsWriter {
109 explicit JSONResultsWriter(const char filename[])
110 : fFilename(filename)
112 , fResults(fRoot["results"])
116 virtual void option(const char name[], const char value[]) {
117 fRoot["options"][name] = value;
119 virtual void bench(const char name[], int32_t x, int32_t y) {
120 SkString sk_name(name);
122 sk_name.appendS32(x);
124 sk_name.appendS32(y);
125 Json::Value* bench_node = SkFindNamedNode(&fResults, sk_name.c_str());
126 fBench = &(*bench_node)["results"];
128 virtual void config(const char name[]) {
129 SkASSERT(NULL != fBench);
130 fConfig = SkFindNamedNode(fBench, name);
132 virtual void timer(const char name[], double ms) {
133 SkASSERT(NULL != fConfig);
134 (*fConfig)[name] = ms;
137 SkFILEWStream stream(fFilename.c_str());
138 stream.writeText(Json::FastWriter().write(fRoot).c_str());
145 Json::Value& fResults;
147 Json::Value* fConfig;
151 * This ResultsWriter writes out to multiple ResultsWriters.
153 class MultiResultsWriter : public ResultsWriter {
155 MultiResultsWriter() : writers() {
157 void add(ResultsWriter* writer) {
158 writers.push_back(writer);
160 virtual void option(const char name[], const char value[]) {
161 for (int i = 0; i < writers.count(); ++i) {
162 writers[i]->option(name, value);
165 virtual void bench(const char name[], int32_t x, int32_t y) {
166 for (int i = 0; i < writers.count(); ++i) {
167 writers[i]->bench(name, x, y);
170 virtual void config(const char name[]) {
171 for (int i = 0; i < writers.count(); ++i) {
172 writers[i]->config(name);
175 virtual void timer(const char name[], double ms) {
176 for (int i = 0; i < writers.count(); ++i) {
177 writers[i]->timer(name, ms);
181 for (int i = 0; i < writers.count(); ++i) {
186 SkTArray<ResultsWriter *> writers;
190 * Calls the end() method of T on destruction.
192 template <typename T> class CallEnd : SkNoncopyable {
194 CallEnd(T& obj) : fObj(obj) {}
195 ~CallEnd() { fObj.end(); }