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