/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * * Classes for writing out bench results in various formats. */ #ifndef SkResultsWriter_DEFINED #define SkResultsWriter_DEFINED #include "BenchLogger.h" #include "SkJSONCPP.h" #include "SkStream.h" #include "SkString.h" #include "SkTArray.h" #include "SkTypes.h" /** * Base class for writing out the bench results. * * Default implementation does nothing. */ class ResultsWriter : SkNoncopyable { public: virtual ~ResultsWriter() {} // Record one key value pair that makes up a unique key for this type of run, e.g. // builder name, machine type, Debug/Release, etc. virtual void key(const char name[], const char value[]) {} // Record one key value pair that describes the run instance, e.g. git hash, build number. virtual void property(const char name[], const char value[]) {} // Denote the start of a specific benchmark. Once bench is called, // then config and timer can be called multiple times to record runs. virtual void bench(const char name[], int32_t x, int32_t y) {} // Record the specific configuration a bench is run under, such as "8888". virtual void config(const char name[]) {} // Record the options for a configuration, such as "GL_RENDERER". virtual void configOption(const char name[], const char* value) {} // Record a single test metric. virtual void timer(const char name[], double ms) {} }; /** NanoJSONResultsWriter writes the test results out in the following format: { "key": { "arch": "Arm7", "gpu": "SGX540", "os": "Android", "model": "GalaxyNexus", } "gitHash": "d1830323662ae8ae06908b97f15180fd25808894", "build_number": "1234", "results" : { "Xfermode_Luminosity_640_480" : { "8888" : { "median_ms" : 143.188128906250, "min_ms" : 143.835957031250, ... }, ... */ class NanoJSONResultsWriter : public ResultsWriter { public: explicit NanoJSONResultsWriter(const char filename[]) : fFilename(filename) , fRoot() , fResults(fRoot["results"]) , fBench(NULL) , fConfig(NULL) {} ~NanoJSONResultsWriter() { SkFILEWStream stream(fFilename.c_str()); stream.writeText(Json::StyledWriter().write(fRoot).c_str()); stream.flush(); } // Added under "key". virtual void key(const char name[], const char value[]) { fRoot["key"][name] = value; } // Inserted directly into the root. virtual void property(const char name[], const char value[]) { fRoot[name] = value; } virtual void bench(const char name[], int32_t x, int32_t y) { SkString id = SkStringPrintf( "%s_%d_%d", name, x, y); fResults[id.c_str()] = Json::Value(Json::objectValue); fBench = &fResults[id.c_str()]; } virtual void config(const char name[]) { SkASSERT(fBench); fConfig = &(*fBench)[name]; } virtual void configOption(const char name[], const char* value) { (*fConfig)["options"][name] = value; } virtual void timer(const char name[], double ms) { // Don't record if nan, or -nan. if (sk_double_isnan(ms)) { return; } SkASSERT(fConfig); (*fConfig)[name] = ms; } private: SkString fFilename; Json::Value fRoot; Json::Value& fResults; Json::Value* fBench; Json::Value* fConfig; }; #endif