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