• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
~ResultsWriter()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:
LoggerResultsWriter(SkBenchLogger & logger,const char * timeFormat)53     explicit LoggerResultsWriter(SkBenchLogger& logger, const char* timeFormat)
54         : fLogger(logger)
55         , fTimeFormat(timeFormat) {
56         fLogger.logProgress("skia bench:");
57     }
option(const char name[],const char value[])58     virtual void option(const char name[], const char value[]) {
59         fLogger.logProgress(SkStringPrintf(" %s=%s", name, value));
60     }
bench(const char name[],int32_t x,int32_t y)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));
64     }
config(const char name[])65     virtual void config(const char name[]) {
66         fLogger.logProgress(SkStringPrintf("   %s:", name));
67     }
timer(const char name[],double ms)68     virtual void timer(const char name[], double ms) {
69         fLogger.logProgress(SkStringPrintf("  %s = ", name));
70         fLogger.logProgress(SkStringPrintf(fTimeFormat, ms));
71     }
end()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:
JSONResultsWriter(const char filename[])102     explicit JSONResultsWriter(const char filename[])
103         : fFilename(filename)
104         , fRoot()
105         , fResults(fRoot["results"])
106         , fBench(NULL)
107         , fConfig(NULL) {
108     }
option(const char name[],const char value[])109     virtual void option(const char name[], const char value[]) {
110         fRoot["options"][name] = value;
111     }
bench(const char name[],int32_t x,int32_t y)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     }
config(const char name[])115     virtual void config(const char name[]) {
116         SkASSERT(NULL != fBench);
117         fConfig = &(*fBench)[name];
118     }
timer(const char name[],double ms)119     virtual void timer(const char name[], double ms) {
120         SkASSERT(NULL != fConfig);
121         (*fConfig)[name] = ms;
122     }
end()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:
MultiResultsWriter()141     MultiResultsWriter() : writers() {
142     };
add(ResultsWriter * writer)143     void add(ResultsWriter* writer) {
144       writers.push_back(writer);
145     }
option(const char name[],const char value[])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     }
bench(const char name[],int32_t x,int32_t y)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     }
config(const char name[])156     virtual void config(const char name[]) {
157         for (int i = 0; i < writers.count(); ++i) {
158             writers[i]->config(name);
159         }
160     }
timer(const char name[],double ms)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     }
end()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:
CallEnd(T & obj)180     CallEnd(T& obj) : fObj(obj) {}
~CallEnd()181     ~CallEnd() { fObj.end(); }
182 private:
183     T&  fObj;
184 };
185 
186 #endif
187