VisualBenchTest: Write JSON output
[platform/upstream/libSkiaSharp.git] / bench / ResultsWriter.h
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
10 #ifndef SkResultsWriter_DEFINED
11 #define SkResultsWriter_DEFINED
12
13 #include "BenchLogger.h"
14 #include "SkJSONCPP.h"
15 #include "SkOSFile.h"
16 #include "SkStream.h"
17 #include "SkString.h"
18 #include "SkTArray.h"
19 #include "SkTypes.h"
20
21 /**
22  * Base class for writing out the bench results.
23  *
24  * Default implementation does nothing.
25  */
26 class ResultsWriter : SkNoncopyable {
27 public:
28     virtual ~ResultsWriter() {}
29
30     // Record one key value pair that makes up a unique key for this type of run, e.g.
31     // builder name, machine type, Debug/Release, etc.
32     virtual void key(const char name[], const char value[]) {}
33
34     // Record one key value pair that describes the run instance, e.g. git hash, build number.
35     virtual void property(const char name[], const char value[]) {}
36
37     // Denote the start of a specific benchmark. Once bench is called,
38     // then config and metric can be called multiple times to record runs.
39     virtual void bench(const char name[], int32_t x, int32_t y) {}
40
41     // Record the specific configuration a bench is run under, such as "8888".
42     virtual void config(const char name[]) {}
43
44     // Record the options for a configuration, such as "GL_RENDERER".
45     virtual void configOption(const char name[], const char* value) {}
46
47     // Record a single test metric.
48     virtual void metric(const char name[], double ms) {}
49
50     // Flush to storage now please.
51     virtual void flush() {}
52 };
53
54 /**
55  NanoJSONResultsWriter writes the test results out in the following
56  format:
57
58  {
59     "key": {
60       "arch": "Arm7",
61       "gpu": "SGX540",
62       "os": "Android",
63       "model": "GalaxyNexus",
64     }
65     "gitHash": "d1830323662ae8ae06908b97f15180fd25808894",
66     "build_number": "1234",
67     "results" : {
68         "Xfermode_Luminosity_640_480" : {
69            "8888" : {
70                  "median_ms" : 143.188128906250,
71                  "min_ms" : 143.835957031250,
72                  ...
73               },
74           ...
75 */
76 class NanoJSONResultsWriter : public ResultsWriter {
77 public:
78     explicit NanoJSONResultsWriter(const char filename[])
79         : fFilename(filename)
80         , fRoot()
81         , fResults(fRoot["results"])
82         , fBench(NULL)
83         , fConfig(NULL) {}
84
85     ~NanoJSONResultsWriter() {
86         this->flush();
87     }
88
89     // Added under "key".
90     virtual void key(const char name[], const char value[]) {
91         fRoot["key"][name] = value;
92     }
93     // Inserted directly into the root.
94     virtual void property(const char name[], const char value[]) {
95         fRoot[name] = value;
96     }
97     virtual void bench(const char name[], int32_t x, int32_t y) {
98         SkString id = SkStringPrintf( "%s_%d_%d", name, x, y);
99         fResults[id.c_str()] = Json::Value(Json::objectValue);
100         fBench = &fResults[id.c_str()];
101     }
102     virtual void config(const char name[]) {
103         SkASSERT(fBench);
104         fConfig = &(*fBench)[name];
105     }
106     virtual void configOption(const char name[], const char* value) {
107         (*fConfig)["options"][name] = value;
108     }
109     virtual void metric(const char name[], double ms) {
110         // Don't record if nan, or -nan.
111         if (sk_double_isnan(ms)) {
112             return;
113         }
114         SkASSERT(fConfig);
115         (*fConfig)[name] = ms;
116     }
117
118     // Flush to storage now please.
119     virtual void flush() {
120         SkString dirname = SkOSPath::Dirname(fFilename.c_str());
121         if (!sk_exists(dirname.c_str(), kWrite_SkFILE_Flag)) {
122             if (!sk_mkdir(dirname.c_str())) {
123                 SkDebugf("Failed to create directory.");
124             }
125         }
126         SkFILEWStream stream(fFilename.c_str());
127         stream.writeText(Json::StyledWriter().write(fRoot).c_str());
128         stream.flush();
129     }
130
131 private:
132     SkString fFilename;
133     Json::Value fRoot;
134     Json::Value& fResults;
135     Json::Value* fBench;
136     Json::Value* fConfig;
137 };
138
139
140 #endif